first commit

This commit is contained in:
Roman Pyrih
2024-12-19 15:27:13 +01:00
commit d6241cfa7a
21694 changed files with 6902106 additions and 0 deletions

View File

@@ -0,0 +1,522 @@
/* global wpforms_builder_providers, wpforms_builder, wpf */
( function( $ ) {
var s;
var WPFormsProviders = {
settings: {
spinner: '<i class="wpforms-loading-spinner wpforms-loading-inline"></i>',
spinnerWhite: '<i class="wpforms-loading-spinner wpforms-loading-inline wpforms-loading-white"></i>',
},
/**
* Start the engine.
*
* @since 1.0.0
*/
init: function() {
s = this.settings;
// Document ready.
$( WPFormsProviders.ready );
WPFormsProviders.bindUIActions();
},
/**
* Document ready.
*
* @since 1.1.1
*/
ready: function() {
// Setup/cache some vars not available before.
s.form = $( '#wpforms-builder-form' );
},
/**
* Element bindings.
*
* @since 1.0.0
*/
bindUIActions: function() {
// Delete connection.
$( document ).on( 'click', '.wpforms-provider-connection-delete', function( e ) {
WPFormsProviders.connectionDelete( this, e );
} );
// Add new connection.
$( document ).on( 'click', '.wpforms-provider-connections-add', function( e ) {
WPFormsProviders.connectionAdd( this, e );
} );
// Add new provider account.
$( document ).on( 'click', '.wpforms-provider-account-add button', function( e ) {
WPFormsProviders.accountAdd( this, e );
} );
// Select provider account.
$( document ).on( 'change', '.wpforms-provider-accounts select', function( e ) {
WPFormsProviders.accountSelect( this, e );
} );
// Select account list.
$( document ).on( 'change', '.wpforms-provider-lists select', function( e ) {
WPFormsProviders.accountListSelect( this, e );
} );
$( document ).on( 'wpformsPanelSwitch', function( e, targetPanel ) {
WPFormsProviders.providerPanelConfirm( targetPanel );
} );
// Alert users if they save a form and do not configure required
// fields.
$( document ).on( 'wpformsSaved', function() {
var providerAlerts = [];
var $connectionBlocks = $( '#wpforms-panel-providers' ).find( '.wpforms-connection-block' );
if ( ! $connectionBlocks.length ) {
return;
}
$connectionBlocks.each( function() {
var requiredEmpty = false,
providerName;
$( this ).find( 'table span.required' ).each( function() {
var $element = $( this ).parent().parent().find( 'select' );
if ( $element.val() === '' ) {
requiredEmpty = true;
}
} );
if ( requiredEmpty ) {
var $titleArea = $( this ).closest( '.wpforms-panel-content-section' ).find( '.wpforms-panel-content-section-title' ).clone();
$titleArea.find( 'button' ).remove();
providerName = $titleArea.text().trim();
var msg = wpforms_builder.provider_required_flds;
if ( -1 < providerAlerts.indexOf( providerName ) ) {
return;
}
$.alert( {
title: wpforms_builder.heads_up,
content: msg.replace( '{provider}', providerName ),
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
},
},
} );
providerAlerts.push( providerName );
}
} );
} );
},
/**
* Delete provider connection
*
* @since 1.0.0
*/
connectionDelete: function( el, e ) {
e.preventDefault();
var $this = $( el );
$.confirm( {
title: false,
content: wpforms_builder_providers.confirm_connection,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: function() {
const $section = $this.closest( '.wpforms-panel-content-section' );
$this.closest( '.wpforms-provider-connection' ).remove();
// Update sidebar icon near the provider.
const provider = $this.closest( '.wpforms-provider-connection' ).data( 'provider' ),
$sidebarItem = $( '.wpforms-panel-sidebar-section-' + provider );
$sidebarItem.find( '.fa-check-circle-o' ).toggleClass( 'wpforms-hidden', $( $section ).find( '.wpforms-provider-connection' ).length <= 0 );
if ( ! $section.find( '.wpforms-provider-connection' ).length ) {
$section.find( '.wpforms-builder-provider-connections-default' ).removeClass( 'wpforms-hidden' );
}
},
},
cancel: {
text: wpforms_builder.cancel,
},
},
} );
},
/**
* Add new provider connection.
*
* @since 1.0.0
*/
connectionAdd: function( el, e ) {
e.preventDefault();
var $this = $( el ),
$connections = $this.parent().parent(),
$container = $this.parent(),
provider = $this.data( 'provider' ),
type = $this.data( 'type' ),
namePrompt = wpforms_builder_providers.prompt_connection,
nameField = '<input autofocus="" type="text" id="provider-connection-name" placeholder="' + wpforms_builder_providers.prompt_placeholder + '">',
nameError = '<p class="error">' + wpforms_builder_providers.error_name + '</p>',
modalContent = namePrompt + nameField + nameError;
modalContent = modalContent.replace( /%type%/g, type );
$.confirm( {
title: false,
content: modalContent,
icon: 'fa fa-info-circle',
type: 'blue',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: function() {
var name = this.$content.find( 'input#provider-connection-name' ).val().trim();
var error = this.$content.find( '.error' );
if ( name === '' ) {
error.show();
return false;
} else {
// Disable button.
WPFormsProviders.inputToggle( $this, 'disable' );
// Fire AJAX.
var data = {
action : 'wpforms_provider_ajax_' + provider,
provider: provider,
task : 'new_connection',
name : name,
id : s.form.data( 'id' ),
nonce : wpforms_builder.nonce,
};
WPFormsProviders.fireAJAX( $this, data, function( res ) {
if ( res.success ) {
$connections.find( '.wpforms-builder-provider-connections-default' ).addClass( 'wpforms-hidden' );
$connections.find( '.wpforms-provider-connections' ).prepend( res.data.html );
// Process and load the accounts if they exist.
var $connection = $connections.find( '.wpforms-provider-connection' ).first();
if ( $connection.find( '.wpforms-provider-accounts option:selected' ) ) {
$connection.find( '.wpforms-provider-accounts option' ).first().prop( 'selected', true );
$connection.find( '.wpforms-provider-accounts select' ).trigger( 'change' );
}
} else {
WPFormsProviders.errorDisplay( res.data.error, $container );
}
} );
}
},
},
cancel: {
text: wpforms_builder.cancel,
},
},
} );
},
/**
* Add and authorize provider account.
*
* @since 1.0.0
*/
accountAdd: function( el, e ) {
e.preventDefault();
var $this = $( el ),
provider = $this.data( 'provider' ),
$connection = $this.closest( '.wpforms-provider-connection' ),
$container = $this.parent(),
$fields = $container.find( ':input' ),
errors = WPFormsProviders.requiredCheck( $fields, $container );
// Disable button.
WPFormsProviders.inputToggle( $this, 'disable' );
// Bail if we have any errors.
if ( errors ) {
$this.prop( 'disabled', false ).find( 'i' ).remove();
return false;
}
// Fire AJAX.
var data = {
action : 'wpforms_provider_ajax_' + provider,
provider : provider,
connection_id: $connection.data( 'connection_id' ),
task : 'new_account',
data : WPFormsProviders.fakeSerialize( $fields ),
};
WPFormsProviders.fireAJAX( $this, data, function( res ) {
if ( res.success ) {
$container.nextAll( '.wpforms-connection-block' ).remove();
$container.nextAll( '.wpforms-conditional-block' ).remove();
$container.after( res.data.html );
$container.slideUp();
$connection.find( '.wpforms-provider-accounts select' ).trigger( 'change' );
} else {
WPFormsProviders.errorDisplay( res.data.error, $container );
}
} );
},
/**
* Selecting a provider account
*
* @since 1.0.0
*/
accountSelect: function( el, e ) {
e.preventDefault();
var $this = $( el ),
$connection = $this.closest( '.wpforms-provider-connection' ),
$container = $this.parent(),
provider = $connection.data( 'provider' );
// Disable select, show loading.
WPFormsProviders.inputToggle( $this, 'disable' );
// Remove any blocks that might exist as we prep for new account.
$container.nextAll( '.wpforms-connection-block' ).remove();
$container.nextAll( '.wpforms-conditional-block' ).remove();
if ( ! $this.val() ) {
// User selected to option to add new account.
$connection.find( '.wpforms-provider-account-add input' ).val( '' );
$connection.find( '.wpforms-provider-account-add' ).slideDown();
WPFormsProviders.inputToggle( $this, 'enable' );
} else {
$connection.find( '.wpforms-provider-account-add' ).slideUp();
// Fire AJAX.
var data = {
action : 'wpforms_provider_ajax_' + provider,
provider : provider,
connection_id: $connection.data( 'connection_id' ),
task : 'select_account',
account_id : $this.find( ':selected' ).val(),
};
WPFormsProviders.fireAJAX( $this, data, function( res ) {
if ( res.success ) {
$container.after( res.data.html );
// Process first list found.
$connection.find( '.wpforms-provider-lists option' ).first().prop( 'selected', true );
$connection.find( '.wpforms-provider-lists select' ).trigger( 'change' );
} else {
WPFormsProviders.errorDisplay( res.data.error, $container );
}
} );
}
},
/**
* Selecting a provider account list.
*
* @since 1.0.0
*/
accountListSelect: function( el, e ) {
e.preventDefault();
var $this = $( el ),
$connection = $this.closest( '.wpforms-provider-connection' ),
$container = $this.parent(),
provider = $connection.data( 'provider' );
// Disable select, show loading.
WPFormsProviders.inputToggle( $this, 'disable' );
// Remove any blocks that might exist as we prep for new account.
$container.nextAll( '.wpforms-connection-block' ).remove();
$container.nextAll( '.wpforms-conditional-block' ).remove();
var data = {
action : 'wpforms_provider_ajax_' + provider,
provider : provider,
connection_id: $connection.data( 'connection_id' ),
task : 'select_list',
account_id : $connection.find( '.wpforms-provider-accounts option:selected' ).val(),
list_id : $this.find( ':selected' ).val(),
form_id : s.form.data( 'id' ),
};
WPFormsProviders.fireAJAX( $this, data, function( res ) {
if ( res.success ) {
$container.after( res.data.html );
// Re-init tooltips for new fields.
wpf.initTooltips();
} else {
WPFormsProviders.errorDisplay( res.data.error, $container );
}
} );
},
/**
* Confirm form save before loading Provider panel.
* If confirmed, save and reload panel.
*
* @since 1.0.0
*/
providerPanelConfirm: function( targetPanel ) {
wpforms_panel_switch = true;
if ( targetPanel === 'providers' && ! s.form.data( 'revision' ) ) {
if ( wpf.savedState != wpf.getFormState( '#wpforms-builder-form' ) ) {
wpforms_panel_switch = false;
$.confirm( {
title: false,
content: wpforms_builder_providers.confirm_save,
icon: 'fa fa-info-circle',
type: 'blue',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: function() {
$( '#wpforms-save' ).trigger( 'click' );
$( document ).on( 'wpformsSaved', function() {
window.location.href = wpforms_builder_providers.url;
} );
},
},
cancel: {
text: wpforms_builder.cancel,
},
},
} );
}
}
},
//--------------------------------------------------------------------//
// Helper functions.
//--------------------------------------------------------------------//
/**
* Fire AJAX call.
*
* @since 1.0.0
*/
fireAJAX: function( el, d, success ) {
var $this = $( el );
var data = {
id : $( '#wpforms-builder-form' ).data( 'id' ),
nonce : wpforms_builder.nonce,
};
$.extend( data, d );
$.post( wpforms_builder.ajax_url, data, function( res ) {
success( res );
WPFormsProviders.inputToggle( $this, 'enable' );
} ).fail( function( xhr, textStatus, e ) {
console.log( xhr.responseText );
} );
},
/**
* Toggle input with loading indicator.
*
* @since 1.0.0
*/
inputToggle: function( el, status ) {
var $this = $( el );
if ( status === 'enable' ) {
if ( $this.is( 'select' ) ) {
$this.prop( 'disabled', false ).next( 'i' ).remove();
} else {
$this.prop( 'disabled', false ).find( 'i' ).remove();
}
} else if ( status === 'disable' ) {
if ( $this.is( 'select' ) ) {
$this.prop( 'disabled', true ).after( s.spinner );
} else {
$this.prop( 'disabled', true ).prepend( s.spinnerWhite );
}
}
},
/**
* Display error.
*
* @since 1.0.0
*/
errorDisplay: function( msg, location ) {
location.find( '.wpforms-error-msg' ).remove();
location.prepend( '<p class="wpforms-alert-danger wpforms-alert wpforms-error-msg">' + msg + '</p>' );
},
/**
* Check for required fields.
*
* @since 1.0.0
*/
requiredCheck: function( fields, location ) {
var error = false;
// Remove any previous errors.
location.find( '.wpforms-alert-required' ).remove();
// Loop through input fields and check for values.
fields.each( function( index, el ) {
if ( $( el ).hasClass( 'wpforms-required' ) && $( el ).val().length === 0 ) {
$( el ).addClass( 'wpforms-error' );
error = true;
} else {
$( el ).removeClass( 'wpforms-error' );
}
} );
if ( error ) {
location.prepend( '<p class="wpforms-alert-danger wpforms-alert wpforms-alert-required">' + wpforms_builder_providers.required_field + '</p>' );
}
return error;
},
/**
* Pseudo serializing. Fake it until you make it.
*
* @since 1.0.0
*/
fakeSerialize: function( els ) {
var fields = els.clone();
fields.each( function( index, el ) {
if ( $( el ).data( 'name' ) ) {
$( el ).attr( 'name', $( el ).data( 'name' ) );
}
} );
return fields.serialize();
},
};
WPFormsProviders.init();
} )( jQuery );

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,716 @@
// noinspection ES6ConvertVarToLetConst
/* global wpf, WPFormsBuilder, WPSplash */
/**
* Context menu module.
*
* @since 1.8.6
*/
var WPForms = window.WPForms || {}; // eslint-disable-line no-var
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.ContextMenu = WPForms.Admin.Builder.ContextMenu || ( function( document, window, $ ) {
/**
* Elements holder.
*
* @since 1.8.6
*
* @type {Object}
*/
const el = {};
/**
* Public functions and properties.
*
* @since 1.8.6
*
* @type {Object}
*/
const app = {
/**
* CSS selectors.
*
* @since 1.8.6
*
* @type {Object}
*/
selectors: {
contextMenu: '.wpforms-context-menu',
mainContextMenuContainer: '#wpforms-context-menu-container',
mainContextMenu: '#wpforms-context-menu',
fieldContextMenu: '#wpforms-field-context-menu',
contextMenuItem: '.wpforms-context-menu:not(.wpforms-context-menu-dropdown) .wpforms-context-menu-list-item',
contextMenuSelectiveItem: '.wpforms-context-menu-list-item-selective',
contextMenuDivider: '.wpforms-context-menu .wpforms-context-menu-list-divider',
builder: '#wpforms-builder',
sidebarToggle: '.wpforms-panels .wpforms-panel-sidebar-content .wpforms-panel-sidebar-toggle',
},
/**
* Start the engine. DOM is not ready yet, use only to init something.
*
* @since 1.8.6
*/
init() {
$( app.ready );
},
/**
* DOM is fully loaded.
*
* @since 1.8.6
*/
ready() {
app.setup();
app.events();
},
/**
* Setup. Prepare some variables.
*
* @since 1.8.6
*/
setup() {
// Cache DOM elements.
el.$document = $( document );
el.$contextMenu = $( app.selectors.contextMenu );
el.$mainContextMenuContainer = $( app.selectors.mainContextMenuContainer );
el.$mainContextMenu = $( app.selectors.mainContextMenu );
el.$fieldContextMenu = $( app.selectors.fieldContextMenu );
el.$contextMenuItem = $( app.selectors.contextMenuItem );
el.$contextMenuSelectiveItem = $( app.selectors.contextMenuSelectiveItem );
el.$contextMenuDivider = $( app.selectors.contextMenuDivider );
el.$builder = $( app.selectors.builder );
el.$sidebarToggle = $( app.selectors.sidebarToggle );
},
/**
* Bind events.
*
* @since 1.8.6
*/
events() {
// Display a main menu on click on the icon in the toolbar.
el.$mainContextMenuContainer.on( 'click', ( event ) => {
event.preventDefault();
el.$mainContextMenu.fadeToggle( 150, () => {
el.$mainContextMenuContainer.toggleClass( 'wpforms-context-menu-active' );
} );
} );
// Handle clicks on the main menu items.
el.$mainContextMenu.on( 'click', '.wpforms-context-menu-list-item', app.mainMenuItemClickAction );
// Hide the main menu if it's visible when clicking outside it.
el.$builder.on( 'click contextmenu', app.hideMainContextMenu );
// Display a context menu on right-click on the form field in the preview area.
el.$document.on( 'contextmenu', app.rightClickContextMenuHandler );
el.$document.on( 'click', app.hideMenuOnClick );
el.$builder.on( 'wpformsFieldTabToggle', app.hideMenuOnClick );
},
/**
* Right-click context menu handler.
*
* @since 1.8.8
*
* @param {KeyboardEvent} e Event object.
*/
rightClickContextMenuHandler( e ) {
const $field = $( e.target ).closest( '.wpforms-field' );
const $panel = $field.closest( '#wpforms-panel-fields' );
if ( ! $panel.length || ! $field.length || $( e.target ).closest( app.selectors.contextMenu ).length ) {
return;
}
app.hideMenu();
if ( e.ctrlKey ) {
return;
}
e.preventDefault();
setTimeout( function() {
app.checkMenuItemsVisibility( $field );
app.checkDividerVisibility();
app.menuPositioning( e );
app.menuItemClickAction( $field );
app.checkSelectiveMenuItemsState( $field );
}, 150 );
},
/**
* Hide the main context menu when clicking outside it.
*
* @since 1.8.8
*
* @param {Event} event Event object.
*/
hideMainContextMenu( event ) {
if ( el.$mainContextMenu.is( ':hidden' ) || $( event.target ).closest( app.selectors.mainContextMenuContainer ).length > 0 ) {
return;
}
el.$mainContextMenu.fadeOut( 150, () => {
el.$mainContextMenuContainer.removeClass( 'wpforms-context-menu-active' );
} );
},
/**
* Main menu item click action.
*
* @since 1.8.8
*/
mainMenuItemClickAction() {
const $item = $( this );
const action = $item.data( 'action' );
const actionUrl = $item.data( 'action-url' ) ?? '';
const actionHandlers = {
'duplicate-form': () => app.handleUrlAction( actionUrl, false, true ),
'save-as-template': () => app.handleUrlAction( actionUrl, false, true ),
'duplicate-template': () => app.handleUrlAction( actionUrl, false, true ),
'view-entries': () => app.handleUrlAction( actionUrl, true ),
'view-payments': () => app.handleUrlAction( actionUrl, true ),
'keyboard-shortcuts': WPFormsBuilder.openKeyboardShortcutsModal,
'whats-new': app.handleWhatsNewAction,
};
const handler = actionHandlers[ action ];
if ( handler ) {
handler();
}
},
/**
* Menu item click action.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
*/
menuItemClickAction( $field ) {
const fieldId = $field.data( 'field-id' );
el.$contextMenuItem.off( 'click' ).on( 'click', function() {
const $item = $( this );
if ( $item.hasClass( 'wpforms-context-menu-list-item-has-child' ) ) {
return;
}
const action = $item.data( 'action' );
const actionHandlers = {
edit: () => app.handleEditAction( $field, fieldId ),
duplicate: () => app.handleDuplicateAction( $field ),
delete: () => app.handleDeleteAction( $field ),
required: () => app.handleRequiredAction( $item, fieldId ),
label: () => app.handleLabelAction( $item, fieldId ),
'smart-logic': () => app.handleSmartLogicAction( $field, fieldId ),
'field-size': () => app.handleSizeAction( $item, fieldId ),
};
const handler = actionHandlers[ action ];
if ( handler ) {
handler();
}
app.hideMenu();
} );
},
/**
* Handle edit action.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
* @param {string} fieldId Field ID.
*/
handleEditAction( $field, fieldId ) {
$field.trigger( 'click' );
// This is needed to make sure the sidebar is open when the "Edit" button is clicked.
app.maybeOpenSidebar();
$( `#wpforms-field-option-basic-${ fieldId } .wpforms-field-option-group-toggle` ).trigger( 'click' );
},
/**
* Handle duplicate action.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
*/
handleDuplicateAction( $field ) {
$field.find( '.wpforms-field-duplicate' ).first().trigger( 'click' );
},
/**
* Handle delete action.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
*/
handleDeleteAction( $field ) {
$field.find( '.wpforms-field-delete' ).first().trigger( 'click' );
},
/**
* Handle required action.
*
* @since 1.8.6
*
* @param {Object} $item Menu item object.
* @param {string} fieldId Field ID.
*/
handleRequiredAction( $item, fieldId ) {
$( `#wpforms-field-option-${ fieldId }-required` ).trigger( 'click' );
const state = app.checkRequiredState( fieldId ) ? 'active' : 'inactive';
app.toggleItemText( $item, state );
},
/**
* Handle label action.
*
* @since 1.8.6
*
* @param {Object} $item Menu item object.
* @param {string} fieldId Field ID.
*/
handleLabelAction( $item, fieldId ) {
$( `#wpforms-field-option-${ fieldId }-label_hide` ).trigger( 'click' );
const state = app.checkLabelState( fieldId ) ? 'active' : 'inactive';
app.toggleItemText( $item, state );
},
/**
* Handle smart logic action.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
* @param {string} fieldId Field ID.
*/
handleSmartLogicAction( $field, fieldId ) {
// This is needed to make sure the sidebar is open when the "Edit Conditional Logic" button is clicked.
app.maybeOpenSidebar();
$field.trigger( 'click' );
$( `#wpforms-field-option-conditionals-${ fieldId } .wpforms-field-option-group-toggle` ).trigger( 'click' );
$( `#wpforms-field-option-${ fieldId } .wpforms-field-option-group-conditionals .education-modal` ).trigger( 'click' );
},
/**
* Handle size action.
*
* @since 1.8.6
*
* @param {Object} $item Menu item object.
* @param {string} fieldId Field ID.
*/
handleSizeAction( $item, fieldId ) {
const value = $item.data( 'value' );
$( `#wpforms-field-option-${ fieldId }-size` ).val( value ).trigger( 'change' );
$item.addClass( 'wpforms-context-menu-list-item-active' ).siblings().removeClass( 'wpforms-context-menu-list-item-active' );
},
/**
* Handle "What's New" action.
*
* @since 1.8.8
*/
handleWhatsNewAction() {
const modal = $( '#tmpl-wpforms-splash-modal-content' );
if ( modal.length && typeof WPSplash !== 'undefined' ) {
WPSplash.openModal();
}
},
/**
* Handle a simple URL action.
*
* @since 1.8.8
*
* @param {string} actionUrl URL.
* @param {boolean} newTab Whether to open the URL in a new tab.
* @param {boolean} saveForm Whether to save the form before following the action URL.
*/
handleUrlAction( actionUrl, newTab = false, saveForm = false ) {
if ( ! actionUrl ) {
return;
}
// The form does not need to be saved, open the URL.
if ( ! saveForm ) {
newTab ? window.open( actionUrl ) : window.location.assign( actionUrl ); // eslint-disable-line no-unused-expressions
return;
}
const isModified = wpf.savedState !== wpf.getFormState( '#wpforms-builder-form' );
// The form was changed and must be saved before following the action URL.
if ( isModified ) {
el.$builder.on( 'wpformsSaved', () => {
newTab ? window.open( actionUrl ) : window.location.assign( actionUrl ); // eslint-disable-line no-unused-expressions
} );
WPFormsBuilder.formSave( false );
return;
}
// The form was not changed, open the URL.
newTab ? window.open( actionUrl ) : window.location.assign( actionUrl ); // eslint-disable-line no-unused-expressions
},
/**
* Toggle item text.
*
* @since 1.8.6
*
* @param {Object} $item Menu item object.
* @param {string} state State.
*/
toggleItemText( $item, state ) {
const $text = $item.find( '.wpforms-context-menu-list-item-text' );
const activeText = $text.data( 'active-text' );
const inactiveText = $text.data( 'inactive-text' ) || $text.text();
if ( ! activeText ) {
return;
}
$text.data( 'inactive-text', inactiveText );
$text.text( state === 'active' ? activeText : inactiveText );
},
/**
* Check selective menu items state.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
*/
checkSelectiveMenuItemsState( $field ) {
const fieldId = $field.data( 'field-id' );
el.$contextMenuSelectiveItem.each( function() {
const $item = $( this );
const action = $item.data( 'action' );
const value = $item.data( 'value' );
const shouldChangeStateHandlers = {
required: () => app.checkRequiredState( fieldId ),
label: () => app.checkLabelState( fieldId ),
'field-size': () => app.checkFieldSizeState( fieldId, value ),
};
const handler = shouldChangeStateHandlers[ action ];
if ( handler() ) {
$item.addClass( 'wpforms-context-menu-list-item-active' );
app.toggleItemText( $item, 'active' );
} else {
$item.removeClass( 'wpforms-context-menu-list-item-active' );
app.toggleItemText( $item, 'inactive' );
}
} );
},
/**
* Check the required state.
*
* @since 1.8.6
*
* @param {string} fieldId Field ID.
*
* @return {boolean} True if option checked.
*/
checkRequiredState( fieldId ) {
return $( `#wpforms-field-option-${ fieldId }-required[type="checkbox"]` ).is( ':checked' );
},
/**
* Check label state.
*
* @since 1.8.6
*
* @param {string} fieldId Field ID.
*
* @return {boolean} True if option checked.
*/
checkLabelState( fieldId ) {
return $( `#wpforms-field-option-${ fieldId }-label_hide[type="checkbox"]` ).is( ':checked' );
},
/**
* Check field size state.
*
* @since 1.8.6
*
* @param {string} fieldId Field ID.
* @param {string} value Value.
*
* @return {boolean} True if value equals.
*/
checkFieldSizeState( fieldId, value ) {
return $( `#wpforms-field-option-${ fieldId }-size` ).val() === value;
},
/**
* Menu positioning.
*
* @since 1.8.6
*
* @param {Object} e Event object.
*/
menuPositioning( e ) {
const menuWidth = el.$fieldContextMenu.width();
const menuHeight = el.$fieldContextMenu.height();
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
el.$fieldContextMenu.removeClass( 'wpforms-context-menu-selective-left' );
let topPosition = e.pageY;
let leftPosition = e.pageX;
if ( e.pageY + menuHeight > windowHeight ) {
topPosition = windowHeight - menuHeight - 15;
}
if ( e.pageX + menuWidth > windowWidth ) {
leftPosition = windowWidth - menuWidth - 15;
el.$fieldContextMenu.addClass( 'wpforms-context-menu-selective-left' );
}
el.$fieldContextMenu.css( {
top: topPosition + 'px',
left: leftPosition + 'px',
} );
el.$fieldContextMenu.fadeIn( 150 );
},
/**
* Check menu items visibility.
*
* @since 1.8.6
*
* @param {Object} $field jQuery object.
*/
checkMenuItemsVisibility( $field ) {
const fieldId = $field.data( 'field-id' );
const shouldHideHandlers = {
edit: () => app.shouldHideEdit( $field ),
duplicate: () => app.shouldHideDuplicate( $field ),
delete: () => app.shouldHideDelete( $field ),
required: () => app.shouldHideRequired( fieldId ),
label: () => app.shouldHideLabel( fieldId ),
'smart-logic': () => app.shouldHideSmartLogic( fieldId ),
'field-size': () => app.shouldHideFieldSize( fieldId, $field ),
};
el.$contextMenuItem.each( function() {
const $item = $( this );
const action = $item.data( 'action' );
const handler = shouldHideHandlers[ action ];
if ( handler() ) {
$item.hide();
}
} );
},
/**
* Check edit visibility.
*
* @since 1.8.7
*
* @param {Object} $field Field object.
*
* @return {boolean} True when should hide.
*/
shouldHideEdit( $field ) {
return $field.hasClass( 'internal-information-not-editable' );
},
/**
* Check duplicate visibility.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
*
* @return {boolean} True when should hide.
*/
shouldHideDuplicate( $field ) {
const $duplicate = $field.find( '.wpforms-field-duplicate' );
return $duplicate.length === 0 || $duplicate.css( 'display' ) === 'none';
},
/**
* Check delete visibility.
*
* @since 1.8.6
*
* @param {Object} $field Field object.
*
* @return {boolean} True when should hide.
*/
shouldHideDelete( $field ) {
const $delete = $field.find( '.wpforms-field-delete' );
return $delete.length === 0 || $delete.css( 'display' ) === 'none';
},
/**
* Check the required visibility.
*
* @since 1.8.6
*
* @param {string} fieldId Field ID.
*
* @return {boolean} True when should hide.
*/
shouldHideRequired( fieldId ) {
return $( `#wpforms-field-option-${ fieldId }-required[type="checkbox"]` ).length === 0;
},
/**
* Check label visibility.
*
* @since 1.8.6
*
* @param {string} fieldId Field ID.
*
* @return {boolean} True when should hide.
*/
shouldHideLabel( fieldId ) {
const $label = $( `#wpforms-field-option-${ fieldId }-label_hide[type="checkbox"]` );
return $label.length === 0 || $label.parents( '.wpforms-field-option-row' ).hasClass( 'wpforms-disabled' );
},
/**
* Check field size visibility.
*
* @since 1.8.6
*
* @param {string} fieldId Field ID.
* @param {Object} $field Field object.
*
* @return {boolean} True when should hide.
*/
shouldHideFieldSize( fieldId, $field ) {
const isFieldInColumn = $field.closest( '.wpforms-layout-column' ).length > 0;
const isRepeaterField = $field.closest( '.wpforms-field-repeater' ).length > 0;
const $size = $( `#wpforms-field-option-${ fieldId }-size` );
return $size.length === 0 || isFieldInColumn || isRepeaterField || $size.parent().hasClass( 'wpforms-hidden' );
},
/**
* Check smart logic visibility.
*
* @since 1.8.6
*
* @param {string} fieldId Field ID.
*
* @return {boolean} True when should hide.
*/
shouldHideSmartLogic( fieldId ) {
return $( `#wpforms-field-option-conditionals-${ fieldId }` ).length === 0 && $( `#wpforms-field-option-${ fieldId } .wpforms-field-option-group-conditionals .education-modal` ).length === 0;
},
/**
* Check divider visibility.
*
* @since 1.8.6
*/
checkDividerVisibility() {
el.$contextMenuDivider.each( function() {
const $divider = $( this );
const visibility = $divider.data( 'visibility' ) ?? '';
let shouldHide = true;
visibility.split( ',' ).forEach( function( item ) {
if ( $( '.wpforms-context-menu-list-item[data-action="' + item.trim() + '"]' ).css( 'display' ) !== 'none' ) {
shouldHide = false;
}
} );
if ( shouldHide ) {
$divider.hide();
} else {
$divider.show();
}
} );
},
/**
* Hide menu.
*
* @since 1.8.6
*/
hideMenu() {
el.$fieldContextMenu.fadeOut( 150 );
setTimeout( function() {
el.$contextMenuItem.show();
}, 150 );
},
/**
* Hide menu on click.
*
* @since 1.8.6
*
* @param {Object} e Event object.
*/
hideMenuOnClick( e ) {
if ( $( e.target ).closest( app.selectors.contextMenu ).length ) {
return;
}
app.hideMenu();
},
/**
* Maybe open the sidebar.
*
* @since 1.8.8
*/
maybeOpenSidebar() {
// If the sidebar is already open, do nothing.
if ( ! el.$sidebarToggle.parent().hasClass( 'wpforms-panel-sidebar-closed' ) ) {
return;
}
el.$sidebarToggle.trigger( 'click' );
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.ContextMenu.init();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,787 @@
/* global wpforms_builder, WPFormsBuilder, WPFormsUtils */
/**
* @param wpforms_builder.field_cannot_be_reordered
*/
// noinspection ES6ConvertVarToLetConst
/**
* Form Builder Fields Drag-n-Drop module.
*
* @since 1.7.7
*/
var WPForms = window.WPForms || {}; // eslint-disable-line no-var
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.DragFields = WPForms.Admin.Builder.DragFields || ( function( document, window, $ ) {
/**
* Elements holder.
*
* @since 1.7.7
*
* @type {Object}
*/
let el = {};
/**
* Runtime variables.
*
* @since 1.7.7
*
* @type {Object}
*/
const vars = {};
/**
* Layout field functions wrapper.
*
* @since 1.7.7
*
* @type {Object}
*/
let fieldLayout; // eslint-disable-line prefer-const
/**
* Public functions and properties.
*
* @since 1.7.7
*
* @type {Object}
*/
const app = {
/**
* Start the engine.
*
* @since 1.7.7
*/
init() {
$( app.ready );
},
/**
* DOM is fully loaded.
*
* @since 1.7.7
*/
ready() {
app.setup();
app.initSortableFields();
app.events();
},
/**
* Setup. Prepare some variables.
*
* @since 1.7.7
*/
setup() {
// Cache DOM elements.
el = {
$builder: $( '#wpforms-builder' ),
$sortableFieldsWrap: $( '#wpforms-panel-fields .wpforms-field-wrap' ),
$addFieldsButtons: $( '.wpforms-add-fields-button' ).not( '.not-draggable' ).not( '.warning-modal' ).not( '.education-modal' ),
};
},
/**
* Bind events.
*
* @since 1.7.7
*/
events() {
el.$builder
.on( 'wpformsFieldDragToggle', app.fieldDragToggleEvent );
},
/**
* Disable drag & drop.
*
* @since 1.7.1
* @since 1.7.7 Moved from admin-builder.js.
*/
disableDragAndDrop() {
el.$addFieldsButtons.filter( '.ui-draggable' ).draggable( 'disable' );
el.$sortableFieldsWrap.sortable( 'disable' );
el.$sortableFieldsWrap.find( '.wpforms-layout-column.ui-sortable' ).sortable( 'disable' );
},
/**
* Enable drag & drop.
*
* @since 1.7.1
* @since 1.7.7 Moved from admin-builder.js.
*/
enableDragAndDrop() {
el.$addFieldsButtons.filter( '.ui-draggable' ).draggable( 'enable' );
el.$sortableFieldsWrap.sortable( 'enable' );
el.$sortableFieldsWrap.find( '.wpforms-layout-column.ui-sortable' ).sortable( 'enable' );
},
/**
* Show popup in case if field is not draggable, and cancel moving.
*
* @since 1.7.5
* @since 1.7.7 Moved from admin-builder.js.
*
* @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 ) {
if ( $field.hasClass( 'ui-draggable-disabled' ) ) {
// noinspection JSUnresolvedReference
$field.draggable( 'enable' );
return;
}
let startTopPosition;
// noinspection JSUnresolvedReference
$field.draggable( {
revert: true,
axis: 'y',
delay: 100,
opacity: 1,
cursor: 'move',
start( event, ui ) {
startTopPosition = ui.position.top;
},
drag( event, ui ) {
if ( Math.abs( ui.position.top ) - Math.abs( startTopPosition ) > 15 ) {
if ( showPopUp ) {
app.youCantReorderFieldPopup();
}
return false;
}
},
} );
},
/**
* Allow field dragging.
*
* @since 1.7.5
* @since 1.7.7 Moved from admin-builder.js.
*
* @param {jQuery} $field A field or list of fields.
*/
fieldDragEnable( $field ) {
if ( $field.hasClass( 'ui-draggable' ) ) {
return;
}
// noinspection JSUnresolvedReference
$field.draggable( 'disable' );
},
/**
* Show the error message in the popup that you cannot reorder the field.
*
* @since 1.7.1
* @since 1.7.7 Moved from admin-builder.js.
*/
youCantReorderFieldPopup() {
$.confirm( {
title: wpforms_builder.heads_up,
content: wpforms_builder.field_cannot_be_reordered,
icon: 'fa fa-exclamation-circle',
type: 'red',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
},
},
} );
},
/**
* Event handler for `wpformsFieldDragToggle` event.
*
* @since 1.7.7
*
* @param {Object} e Event object.
* @param {number|string} id Field ID.
*/
fieldDragToggleEvent( e, id ) {
const $field = $( `#wpforms-field-${ id }` );
if (
$field.hasClass( 'wpforms-field-not-draggable' ) ||
$field.hasClass( 'wpforms-field-stick' )
) {
app.fieldDragDisable( $field );
return;
}
app.fieldDragEnable( $field );
},
/**
* Initialize sortable fields in the builder form preview area.
*
* @since 1.7.7
*/
initSortableFields() {
app.initSortableContainer( el.$sortableFieldsWrap );
el.$builder.find( '.wpforms-layout-column' ).each( function() {
app.initSortableContainer( $( this ) );
} );
app.fieldDragDisable( $( '.wpforms-field-not-draggable, .wpforms-field-stick' ) );
app.initDraggableFields();
},
/**
* Initialize sortable container with fields.
*
* @since 1.7.7
*
* @param {jQuery} $sortable Container to make sortable.
*/
initSortableContainer( $sortable ) { // eslint-disable-line max-lines-per-function
const $fieldOptions = $( '#wpforms-field-options' );
const $scrollContainer = $( '#wpforms-panel-fields .wpforms-panel-content-wrap' );
let fieldId,
fieldType,
isNewField,
$fieldOption,
$prevFieldOption,
prevFieldId,
currentlyScrolling = false;
// noinspection JSUnresolvedReference
$sortable.sortable( {
items: '> .wpforms-field:not(.wpforms-field-stick):not(.no-fields-preview)',
connectWith: '.wpforms-field-wrap, .wpforms-layout-column',
delay: 100,
opacity: 1,
cursor: 'move',
cancel: '.wpforms-field-not-draggable',
placeholder: 'wpforms-field-drag-placeholder',
appendTo: '#wpforms-panel-fields',
zindex: 10000,
tolerance: 'pointer',
distance: 1,
start( e, ui ) {
fieldId = ui.item.data( 'field-id' );
fieldType = ui.item.data( 'field-type' );
isNewField = typeof fieldId === 'undefined';
$fieldOption = $( '#wpforms-field-option-' + fieldId );
vars.fieldReceived = false;
vars.fieldRejected = false;
vars.$sortableStart = $sortable;
vars.startPosition = ui.item.first().index();
el.$builder.trigger( 'wpformsFieldDragStart', [ fieldId ] );
},
beforeStop( e, ui ) {
if ( ! vars.glitchChange ) {
return;
}
// Before processing in the `stop` method, we need to perform the last check.
if ( ! fieldLayout.isFieldAllowedInColum( fieldType, ui.item.first().parent() ) ) {
vars.fieldRejected = true;
}
},
stop( e, ui ) { // eslint-disable-line complexity
const $field = ui.item.first();
ui.placeholder.removeClass( 'wpforms-field-drag-not-allowed' );
$field.removeClass( 'wpforms-field-drag-not-allowed' );
// Reject not allowed fields.
if ( vars.fieldRejected ) {
const $targetColumn = isNewField ? $sortable : $field.parent();
app.revertMoveFieldToColumn( $field );
el.$builder.trigger( 'wpformsFieldMoveRejected', [ $field, ui, $targetColumn ] );
return;
}
prevFieldId = $field.prev( '.wpforms-field, .wpforms-alert' ).data( 'field-id' );
$prevFieldOption = $( `#wpforms-field-option-${ prevFieldId }` );
if ( $prevFieldOption.length > 0 ) {
$prevFieldOption.after( $fieldOption );
} else {
$fieldOptions.prepend( $fieldOption );
}
// In the case of changing fields' order inside the same column,
// we just need to change the position of the field.
if ( ! isNewField && $field.closest( '.wpforms-layout-column' ).is( $sortable ) ) {
fieldLayout.positionFieldInColumn(
fieldId,
$field.index() - 1,
$sortable
);
}
const $layoutField = $field.closest( '.wpforms-field-layout, .wpforms-field-repeater' );
fieldLayout.fieldOptionsUpdate( null, fieldId );
fieldLayout.reorderLayoutFieldsOptions( $layoutField );
if ( ! isNewField ) {
$field
.removeClass( 'wpforms-field-dragging' )
.removeClass( 'wpforms-field-drag-over' );
}
$field.attr( 'style', '' );
el.$builder.trigger( 'wpformsFieldMove', ui );
vars.fieldReceived = false;
},
over( e, ui ) { // eslint-disable-line complexity
const $field = ui.item.first(),
$target = $( e.target ),
$placeholder = $target.find( '.wpforms-field-drag-placeholder' ),
isColumn = $target.hasClass( 'wpforms-layout-column' ),
helper = {
width: $target.outerWidth(),
height: $field.outerHeight(),
};
let targetClass = isColumn ? ' wpforms-field-drag-to-column' : '';
if ( isColumn ) {
const columnSize = $target.attr( 'class' ).match( /wpforms-layout-column-(\d+)/ )[ 1 ];
targetClass += ` wpforms-field-drag-to-column-${ columnSize }`;
}
fieldId = $field.data( 'field-id' );
fieldType = $field.data( 'field-type' ) || vars.fieldType;
isNewField = typeof fieldId === 'undefined';
// Adjust helper size according to the placeholder size.
$field
.addClass( 'wpforms-field-dragging' + targetClass );
if ( ! isColumn || ! fieldLayout.isLayoutBasedField( fieldType ) ) {
$field
.css( {
width: isColumn ? helper.width - 5 : helper.width,
height: 'auto',
} );
}
const placeholderHeight = isColumn ? 90 : helper.height;
// Adjust placeholder height according to the height of the helper.
$placeholder
.removeClass( 'wpforms-field-drag-not-allowed' )
.css( {
height: isNewField ? placeholderHeight + 18 : helper.height,
} );
// Drop to this place is not allowed.
if ( isColumn && ! fieldLayout.isFieldAllowedInColum( fieldType, $target ) ) {
$placeholder.addClass( 'wpforms-field-drag-not-allowed' );
$field.addClass( 'wpforms-field-drag-not-allowed' );
}
el.$builder.trigger( 'wpformsFieldDragOver', [ fieldId, $target ] );
// Skip if it is the existing field.
if ( ! isNewField ) {
return;
}
$field
.addClass( 'wpforms-field-drag-over' )
.removeClass( 'wpforms-field-drag-out' );
},
out( e, ui ) {
const $field = ui.item.first(),
// eslint-disable-next-line no-shadow
fieldId = $field.data( 'field-id' ),
// eslint-disable-next-line no-shadow
isNewField = typeof fieldId === 'undefined';
$field
.removeClass( 'wpforms-field-drag-not-allowed' )
.removeClass( function( index, className ) {
// Remove all classes starting with `wpforms-field-drag-to-column`.
return ( className.match( /wpforms-field-drag-to-column(-\d+|)/g ) || [] ).join( ' ' );
} );
if ( vars.fieldReceived ) {
$field.attr( 'style', '' );
return;
}
// Skip if it is the existing field.
if ( ! isNewField ) {
// Remove extra class from the parent layout field.
// Fixes disappearing of duplicate/delete field icons
// after moving the field outside the layout field.
$( ui.sender )
.closest( '.wpforms-field-layout, .wpforms-field-repeater' )
.removeClass( 'wpforms-field-child-hovered' );
return;
}
$field
.addClass( 'wpforms-field-drag-out' )
.removeClass( 'wpforms-field-drag-over' );
},
receive( e, ui ) { // eslint-disable-line complexity
const $field = $( ui.helper || ui.item );
fieldId = $field.data( 'field-id' );
fieldType = $field.data( 'field-type' ) || vars.fieldType;
// eslint-disable-next-line no-shadow
const isNewField = typeof fieldId === 'undefined',
isColumn = $sortable.hasClass( 'wpforms-layout-column' );
// Drop to this place is not allowed.
if (
isColumn &&
! fieldLayout.isFieldAllowedInColum( fieldType, $sortable )
) {
vars.fieldRejected = true;
return;
}
vars.fieldReceived = true;
$field.removeClass( 'wpforms-field-drag-over' );
// Move existing field.
if ( ! isNewField ) {
fieldLayout.receiveFieldToColumn(
fieldId,
ui.item.index() - 1,
$field.parent()
);
return;
}
// Add new field.
const position = $sortable.data( 'ui-sortable' ).currentItem.index();
$field
.addClass( 'wpforms-field-drag-over wpforms-field-drag-pending' )
.removeClass( 'wpforms-field-drag-out' )
.append( WPFormsBuilder.settings.spinnerInline )
.css( 'width', '100%' );
el.$builder.find( '.no-fields-preview' ).remove();
WPFormsBuilder.fieldAdd(
vars.fieldType,
{
position: isColumn ? position - 1 : position,
placeholder: $field,
$sortable,
}
);
vars.fieldType = undefined;
},
change( e, ui ) {
const $placeholderSortable = ui.placeholder.parent();
const $targetSortable = $( e.target );
vars.glitchChange = false;
// In some cases sortable widget display placeholder in wrong sortable instance.
// It's happens when you drag the field over/out the last column of the last Layout field.
if (
! $sortable.is( $placeholderSortable ) &&
$sortable.hasClass( 'wpforms-field-wrap' ) &&
$placeholderSortable.hasClass( 'wpforms-layout-column' )
) {
vars.glitchChange = true;
}
el.$builder.trigger( 'wpformsFieldDragChange', [ fieldId, $targetSortable ] );
},
sort( e ) {
if ( currentlyScrolling ) {
return;
}
const scrollAreaHeight = 50,
mouseYPosition = e.clientY,
containerOffset = $scrollContainer.offset(),
containerHeight = $scrollContainer.height(),
containerBottom = containerOffset.top + containerHeight;
let operator;
if (
mouseYPosition > containerOffset.top &&
mouseYPosition < ( containerOffset.top + scrollAreaHeight )
) {
operator = '-=';
} else if (
mouseYPosition > ( containerBottom - scrollAreaHeight ) &&
mouseYPosition < containerBottom
) {
operator = '+=';
} else {
return;
}
currentlyScrolling = true;
$scrollContainer.animate(
{
scrollTop: operator + ( containerHeight / 3 ) + 'px',
},
800,
function() {
currentlyScrolling = false;
}
);
},
} );
},
/**
* Initialize draggable fields buttons.
*
* @since 1.7.7
*/
initDraggableFields() {
el.$addFieldsButtons.draggable( {
connectToSortable: '.wpforms-field-wrap, .wpforms-layout-column',
delay: 200,
cancel: false,
scroll: false,
opacity: 1,
appendTo: '#wpforms-panel-fields',
zindex: 10000,
helper() {
const $this = $( this );
const $el = $( '<div class="wpforms-field-drag-out wpforms-field-drag">' );
vars.fieldType = $this.data( 'field-type' );
return $el.html( $this.html() );
},
start( e, ui ) {
const event = WPFormsUtils.triggerEvent(
el.$builder,
'wpformsFieldAddDragStart',
[ vars.fieldType, ui ]
);
// Allow callbacks on `wpformsFieldAddDragStart` to cancel dragging the field
// by triggering `event.preventDefault()`.
if ( event.isDefaultPrevented() ) {
return false;
}
},
stop( e, ui ) {
const event = WPFormsUtils.triggerEvent(
el.$builder,
'wpformsFieldAddDragStop',
[ vars.fieldType, ui ]
);
// Allow callbacks on `wpformsFieldAddDragStop` to cancel dragging the field
// by triggering `event.preventDefault()`.
if ( event.isDefaultPrevented() ) {
return false;
}
},
} );
},
/**
* Revert moving the field to the column.
*
* @since 1.7.7
*
* @param {jQuery} $field Field object.
*/
revertMoveFieldToColumn( $field ) {
const isNewField = $field.data( 'field-id' ) === undefined;
if ( isNewField ) {
// Remove the field.
$field.remove();
return;
}
// Restore existing field on the previous position.
$field = $field.detach();
const $fieldInStartPosition = vars.$sortableStart
.find( '> .wpforms-field' )
.eq( vars.startPosition );
$field
.removeClass( 'wpforms-field-dragging' )
.removeClass( 'wpforms-field-drag-over' )
.attr( 'style', '' );
if ( $fieldInStartPosition.length ) {
$fieldInStartPosition.before( $field );
return;
}
vars.$sortableStart.append( $field );
},
};
/**
* Layout field functions holder.
*
* @since 1.7.7
*
* @type {Object}
*/
fieldLayout = {
/**
* Position field in the column inside the Layout Field.
*
* @since 1.7.7
*
* @param {number} fieldId Field ID.
* @param {number} position The new position of the field inside the column.
* @param {jQuery} $sortable Sortable column container.
*/
positionFieldInColumn( fieldId, position, $sortable ) {
if ( ! WPForms.Admin.Builder.FieldLayout ) {
return;
}
WPForms.Admin.Builder.FieldLayout.positionFieldInColumn( fieldId, position, $sortable );
},
/**
* Receive field to column inside the Layout Field.
*
* @since 1.7.7
*
* @param {number} fieldId Field ID.
* @param {number} position Field position inside the column.
* @param {jQuery} $sortable Sortable column container.
*/
receiveFieldToColumn( fieldId, position, $sortable ) {
if ( ! WPForms.Admin.Builder.FieldLayout ) {
return;
}
WPForms.Admin.Builder.FieldLayout.receiveFieldToColumn( fieldId, position, $sortable );
},
/**
* Update field options according to the position of the field.
* Event `wpformsFieldOptionTabToggle` handler.
*
* @since 1.7.7
*
* @param {Event} e Event.
* @param {number} fieldId Field id.
*/
fieldOptionsUpdate( e, fieldId ) {
if ( ! WPForms.Admin.Builder.FieldLayout ) {
return;
}
WPForms.Admin.Builder.FieldLayout.fieldOptionsUpdate( e, fieldId );
},
/**
* Reorder fields options of the fields in columns.
* It is not critical, but it's better to keep some order in the `fields` data array.
*
* @since 1.7.7
*
* @param {jQuery} $layoutField Layout field object.
*/
reorderLayoutFieldsOptions( $layoutField ) {
if ( ! WPForms.Admin.Builder.FieldLayout ) {
return;
}
WPForms.Admin.Builder.FieldLayout.reorderLayoutFieldsOptions( $layoutField );
},
/**
* Whether the field type is allowed to be in column.
*
* @since 1.7.7
*
* @param {string} fieldType Field type to check.
* @param {jQuery} $targetColumn Target column element.
*
* @return {boolean} True if allowed.
*/
isFieldAllowedInColum( fieldType, $targetColumn ) {
if ( ! WPForms.Admin.Builder.FieldLayout ) {
return true;
}
const isAllowed = WPForms.Admin.Builder.FieldLayout.isFieldAllowedInColum( fieldType, $targetColumn );
/**
* Allows developers to determine whether the field is allowed to be dragged in column.
*
* @since 1.8.9
*
* @param {boolean} isAllowed Whether the field is allowed to be placed in the column.
* @param {string} fieldType Field type.
* @param {jQuery} $targetColumn Target column element.
*
* @return {boolean} True if allowed.
*/
return wp.hooks.applyFilters( 'wpforms.LayoutField.isFieldAllowedDragInColumn', isAllowed, fieldType, $targetColumn );
},
/**
* Determine whether the field type is a layout-based field.
*
* @since 1.8.9
*
* @param {string} fieldType Field type to check.
*
* @return {boolean} True if it is the Layout-based field.
*/
isLayoutBasedField( fieldType ) {
if ( ! WPForms.Admin.Builder.FieldLayout ) {
return false;
}
return WPForms.Admin.Builder.FieldLayout.isLayoutBasedField( fieldType );
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.DragFields.init();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,287 @@
/**
* WPForms Builder Dropdown List module.
*
* @since 1.8.4
*/
/*
Usage:
dropdownList = WPForms.Admin.Builder.DropdownList.init( {
class: 'insert-field-dropdown', // Additional CSS class.
title: 'Dropdown Title', // Dropdown title.
list: [ // Items list.
{ value: '1', text: 'Item 1' },
{ value: '2', text: 'Item 2' },
{ value: '3', text: 'Item 3' },
],
container: $( '.holder-container' ), // Holder container. Optional.
scrollableContainer: $( '.scrollable-container' ), // Scrollable container. Optional.
button: $( '.button' ), // Button.
buttonDistance: 21, // Distance from dropdown to the button.
itemFormat( item ) { // Item element renderer. Optional.
return `<span>${ item.text }</span>`;
},
onSelect( event, value, text, $item, instance ) { // On select event handler.
console.log( 'Item selected:', text );
instance.close();
$button.removeClass( 'active' );
},
} );
*/
var WPForms = window.WPForms || {}; // eslint-disable-line no-var
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.DropdownList = WPForms.Admin.Builder.DropdownList || ( function( document, window, $ ) {
/**
* DropdownList object constructor.
*
* @since 1.8.4
*
* @type {Object}
*/
function DropdownList( options ) { // eslint-disable-line max-lines-per-function
const self = this;
/**
* Default options.
*
* @since 1.8.4
*
* @type {Object}
*/
const defaultOptions = {
class: '',
title: '',
list: [],
container: null,
scrollableContainer: null,
button: null,
buttonDistance: 10,
onSelect: null,
itemFormat( item ) {
return item.text;
},
};
/**
* Options.
*
* @since 1.8.4
*
* @type {jQuery}
*/
self.options = $.extend( defaultOptions, options );
/**
* Main dropdown container.
*
* @since 1.8.4
*
* @type {jQuery}
*/
self.$el = null;
/**
* Form builder container.
*
* @since 1.8.4
*
* @type {jQuery}
*/
self.$builder = $( '#wpforms-builder' );
/**
* Close the dropdown.
*
* @since 1.8.4
*/
self.close = function() {
self.$el.addClass( 'closed' );
};
/**
* Open the dropdown.
*
* @since 1.8.4
*/
self.open = function() {
self.$el.removeClass( 'closed' );
self.setPosition();
// Close dropdown on click outside.
self.$builder.on( 'click.DropdowmList', function( e ) {
const $target = $( e.target );
if ( $target.closest( self.$el ).length || $target.hasClass( 'button-insert-field' ) ) {
return;
}
self.$builder.off( 'click.DropdowmList' );
const $button = $( self.options.button );
if ( $button.hasClass( 'active' ) ) {
$button.trigger( 'click' );
}
} );
};
/**
* Generate the dropdown HTML.
*
* @since 1.8.4
*
* @return {string} HTML.
*/
self.generateHtml = function() {
const list = self.options.list;
if ( ! list || list.length === 0 ) {
return '';
}
const itemFormat = typeof self.options.itemFormat === 'function' ? self.options.itemFormat : defaultOptions.itemFormat;
// Generate HTML.
const items = [];
for ( const i in list ) {
items.push( `<li data-value="${ list[ i ].value }">${ itemFormat( list[ i ] ) }</li>` );
}
return `<div class="wpforms-builder-dropdown-list closed ${ self.options.class }">
<div class="title">${ self.options.title }</div>
<ul>${ items.join( '' ) }</ul>
</div>`;
};
/**
* Attach dropdown to DOM.
*
* @since 1.8.4
*/
self.attach = function() {
const html = self.generateHtml();
// Remove old dropdown.
if ( self.$el && self.$el.length ) {
self.$el.remove();
}
// Create jQuery objects.
self.$el = $( html );
self.$button = $( self.options.button );
self.$container = self.options.container ? $( self.options.container ) : self.$button.parent();
self.$scrollableContainer = self.options.scrollableContainer ? $( self.options.scrollableContainer ) : null;
// Add the dropdown to the container.
self.$container.append( self.$el );
self.setPosition();
};
/**
* Set dropdown position.
*
* @since 1.8.4
*/
self.setPosition = function() {
// Calculate position.
const buttonOffset = self.$button.offset(),
containerOffset = self.$container.offset(),
containerPosition = self.$container.position(),
dropdownHeight = self.$el.height(),
scrollTop = self.$scrollableContainer ? self.$scrollableContainer.scrollTop() : 0;
let top = buttonOffset.top - containerOffset.top - dropdownHeight - self.options.buttonDistance;
// In the case of the dropdown doesn't fit into the scrollable container to top, it is needed to open the dropdown to the bottom.
if ( scrollTop + containerPosition.top - dropdownHeight < 0 ) {
top = buttonOffset.top - containerOffset.top + self.$button.height() + self.options.buttonDistance - 11;
}
self.$el.css( 'top', top );
// The dropdown is outside the field options, it is needed to set `left` positioning value.
if ( self.$container.closest( '.wpforms-field-option' ).length === 0 ) {
self.$el.css( 'left', buttonOffset.left - containerOffset.left );
}
};
/**
* Events.
*
* @since 1.8.4
*/
self.events = function() {
// Click (select) the item.
self.$el.find( 'li' ).off()
.on( 'click', function( event ) {
// Bail if callback is not a function.
if ( typeof self.options.onSelect !== 'function' ) {
return;
}
const $item = $( this );
self.options.onSelect( event, $item.data( 'value' ), $item.text(), $item, self );
} );
};
/**
* Initialize.
*
* @since 1.8.4
*
* @param {Array} list List of items.
*/
self.init = function( list = null ) {
self.options.list = list ? list : self.options.list;
self.attach();
self.events();
self.$button.data( 'dropdown-list', self );
};
/**
* Destroy.
*
* @since 1.8.4
*/
self.destroy = function() {
self.$button.data( 'dropdown-list', null );
self.$el.remove();
};
// Initialize.
self.init();
}
/**
* Public functions and properties.
*
* @since 1.8.4
*
* @type {Object}
*/
return {
/**
* Start the engine. DOM is not ready yet, use only to init something.
*
* @since 1.8.4
*
* @param {Object} options Options.
*
* @return {Object} DropdownList instance.
*/
init( options ) {
return new DropdownList( options );
},
};
}( document, window, jQuery ) );

View File

@@ -0,0 +1,4 @@
var WPForms=window.WPForms||{};WPForms.Admin=WPForms.Admin||{},WPForms.Admin.Builder=WPForms.Admin.Builder||{},WPForms.Admin.Builder.DropdownList=WPForms.Admin.Builder.DropdownList||function(n){function o(t){const s=this,i={class:"",title:"",list:[],container:null,scrollableContainer:null,button:null,buttonDistance:10,onSelect:null,itemFormat(t){return t.text}};s.options=n.extend(i,t),s.$el=null,s.$builder=n("#wpforms-builder"),s.close=function(){s.$el.addClass("closed")},s.open=function(){s.$el.removeClass("closed"),s.setPosition(),s.$builder.on("click.DropdowmList",function(t){var t=n(t.target);t.closest(s.$el).length||t.hasClass("button-insert-field")||(s.$builder.off("click.DropdowmList"),(t=n(s.options.button)).hasClass("active")&&t.trigger("click"))})},s.generateHtml=function(){var t=s.options.list;if(!t||0===t.length)return"";var o=("function"==typeof s.options.itemFormat?s.options:i).itemFormat,n=[];for(const e in t)n.push(`<li data-value="${t[e].value}">${o(t[e])}</li>`);return`<div class="wpforms-builder-dropdown-list closed ${s.options.class}">
<div class="title">${s.options.title}</div>
<ul>${n.join("")}</ul>
</div>`},s.attach=function(){var t=s.generateHtml();s.$el&&s.$el.length&&s.$el.remove(),s.$el=n(t),s.$button=n(s.options.button),s.$container=s.options.container?n(s.options.container):s.$button.parent(),s.$scrollableContainer=s.options.scrollableContainer?n(s.options.scrollableContainer):null,s.$container.append(s.$el),s.setPosition()},s.setPosition=function(){var t=s.$button.offset(),o=s.$container.offset(),n=s.$container.position(),e=s.$el.height(),i=s.$scrollableContainer?s.$scrollableContainer.scrollTop():0;let l=t.top-o.top-e-s.options.buttonDistance;i+n.top-e<0&&(l=t.top-o.top+s.$button.height()+s.options.buttonDistance-11),s.$el.css("top",l),0===s.$container.closest(".wpforms-field-option").length&&s.$el.css("left",t.left-o.left)},s.events=function(){s.$el.find("li").off().on("click",function(t){var o;"function"==typeof s.options.onSelect&&(o=n(this),s.options.onSelect(t,o.data("value"),o.text(),o,s))})},s.init=function(t=null){s.options.list=t||s.options.list,s.attach(),s.events(),s.$button.data("dropdown-list",s)},s.destroy=function(){s.$button.data("dropdown-list",null),s.$el.remove()},s.init()}return{init(t){return new o(t)}}}((document,window,jQuery));

View File

@@ -0,0 +1,217 @@
/* eslint-disable camelcase */
/* global wpforms_builder_email_template */
// noinspection ES6ConvertVarToLetConst
/**
* Script for manipulating DOM events in the "Builder" settings page.
* This script will be accessible in the "WPForms" → "Builder" → "Notifications" tab/page.
*
* @since 1.8.5
*/
// eslint-disable-next-line no-var
var WPFormsBuilderEmailTemplate = window.WPFormsBuilderEmailTemplate || ( function( document, window, $, l10n ) {
/**
* Elements holder.
*
* @since 1.8.5
*
* @type {Object}
*/
const el = {};
/**
* Runtime variables.
*
* @since 1.8.5
*
* @type {Object}
*/
const vars = {
/**
* Modal instance.
*
* @since 1.8.5
*/
modal: null,
/**
* Generic CSS class names for applying visual changes.
*
* @since 1.8.5
*/
classNames: {
modalBox: 'wpforms-modal-content-box',
modalOpen: 'wpforms-email-template-modal-open',
},
};
/**
* Public functions and properties.
*
* @since 1.8.5
*/
const app = {
/**
* Start the engine.
*
* @since 1.8.5
*/
init() {
$( app.ready );
},
/**
* Document ready.
*
* @since 1.8.5
*/
ready() {
app.setup();
app.bindEvents();
},
/**
* Setup. Prepare some variables.
*
* @since 1.8.5
*/
setup() {
// Cache DOM elements.
el.$document = $( document );
el.$body = $( 'body' );
},
/**
* Bind events.
*
* @since 1.8.5
*/
bindEvents() {
el.$document
.on( 'change', '.wpforms-email-template-modal-content input[type="radio"]', app.handleOnChangeTemplate )
.on( 'click', '.wpforms-all-email-template-modal', app.handleOnOpenModal );
},
/**
* Handle the "change" event for the template radio buttons.
* This function updates the select field based on the selected radio button.
*
* @since 1.8.5
*
* @param {Object} event The DOM event that triggered the function.
*/
handleOnChangeTemplate( event ) {
// Prevent the default action, which is to handle the change event.
event.preventDefault();
// Extract the ID of the field from the element.
const id = app.getIdFromElm( $( this ) );
// Get the corresponding select field.
const $field = $( `#wpforms-panel-field-notifications-${ id }-template` );
// If the select field doesn't exist, no further action is needed.
if ( ! $field.length ) {
return;
}
// If the modal doesn't exist, no further action is needed.
if ( ! vars.modal ) {
return;
}
// Get the value of the radio button that triggered the change.
const value = $( this ).val();
// Update the select field with the selected value and trigger the change event.
$field.val( value ).trigger( 'change' );
// Close the modal.
vars.modal.close();
},
/**
* Handle the "click" event for opening the modal.
* This will open the modal with the available templates.
*
* @since 1.8.5
*/
handleOnOpenModal() {
// Get the email template modal template.
const template = wp.template( 'wpforms-email-template-modal' );
// If the template doesn't exist, exit the function.
if ( ! template.length ) {
return;
}
// Find the closest wrapper and select element.
const $wrapper = $( this ).closest( '.wpforms-panel-field-email-template-wrap' );
const $select = $wrapper.find( 'select' );
// Get the selected value from the select element and its ID.
const selected = $select.val() || '';
const id = app.getIdFromElm( $select );
// Extract relevant data from l10n.
const { templates, is_pro } = l10n;
// Prepare the data to be passed to the template.
const data = { templates, selected, is_pro, id };
// Generate the modal's content using the template and data.
const content = template( data );
// Open the modal.
vars.modal = $.confirm( {
content,
title: '',
boxWidth: 800,
contentMaxHeight: 'none',
backgroundDismiss: true,
smoothContent: false,
closeIcon: true,
buttons: false,
// Callback function before the modal opens.
onOpenBefore() {
this.$body.addClass( vars.classNames.modalBox );
el.$body.addClass( vars.classNames.modalOpen );
},
// Callback function when the modal is closed.
onClose() {
el.$body.removeClass( vars.classNames.modalOpen );
},
} );
},
/**
* Get the ID from the element.
* This is a helper function for extracting the numeric ID from an element's ID attribute.
*
* @since 1.8.5
*
* @param {Object} $elm jQuery object representing the element.
*
* @return {number} The numeric ID extracted from the element's ID attribute.
*/
getIdFromElm( $elm ) {
// Get the ID attribute from the element.
const id = $elm.attr( 'id' );
// If no ID attribute is found, return 0.
if ( ! id ) {
return 0;
}
// Extract and parse the numeric part from the ID.
return parseInt( id.match( /\d+/ )[ 0 ], 10 );
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery, wpforms_builder_email_template ) );
// Initialize.
WPFormsBuilderEmailTemplate.init();

View File

@@ -0,0 +1 @@
var WPFormsBuilderEmailTemplate=window.WPFormsBuilderEmailTemplate||function(e,m,n){const s={},d={modal:null,classNames:{modalBox:"wpforms-modal-content-box",modalOpen:"wpforms-email-template-modal-open"}},i={init(){m(i.ready)},ready(){i.setup(),i.bindEvents()},setup(){s.$document=m(e),s.$body=m("body")},bindEvents(){s.$document.on("change",'.wpforms-email-template-modal-content input[type="radio"]',i.handleOnChangeTemplate).on("click",".wpforms-all-email-template-modal",i.handleOnOpenModal)},handleOnChangeTemplate(e){e.preventDefault();var a,e=i.getIdFromElm(m(this)),e=m(`#wpforms-panel-field-notifications-${e}-template`);e.length&&d.modal&&(a=m(this).val(),e.val(a).trigger("change"),d.modal.close())},handleOnOpenModal(){var e,a,l,t,o=wp.template("wpforms-email-template-modal");o.length&&(e=(a=m(this).closest(".wpforms-panel-field-email-template-wrap").find("select")).val()||"",a=i.getIdFromElm(a),{templates:l,is_pro:t}=n,o=o({templates:l,selected:e,is_pro:t,id:a}),d.modal=m.confirm({content:o,title:"",boxWidth:800,contentMaxHeight:"none",backgroundDismiss:!0,smoothContent:!1,closeIcon:!0,buttons:!1,onOpenBefore(){this.$body.addClass(d.classNames.modalBox),s.$body.addClass(d.classNames.modalOpen)},onClose(){s.$body.removeClass(d.classNames.modalOpen)}}))},getIdFromElm(e){e=e.attr("id");return e?parseInt(e.match(/\d+/)[0],10):0}};return i}(document,(window,jQuery),wpforms_builder_email_template);WPFormsBuilderEmailTemplate.init();

View File

@@ -0,0 +1,486 @@
/* global wpforms_builder, wpf, WPFormsBuilder, WPForms, md5 */
'use strict';
/**
* WPForms Internal Information Field builder functions.
*
* @since 1.7.6
*/
var WPFormsInternalInformationField = window.WPFormsInternalInformationField || ( function( document, window, $ ) { // eslint-disable-line
/**
* WPForms builder element.
*
* @since 1.7.6
*
* @type {jQuery}
*/
let $builder;
/**
* Public functions and properties.
*
* @since 1.7.6
*
* @type {object}
*/
let app = {
/**
* Start the engine.
*
* @since 1.7.6
*/
init: function() {
$( app.ready );
},
/**
* Initialized once the DOM is fully loaded.
*
* @since 1.7.6
*/
ready: function() {
$builder = $( '#wpforms-builder' );
app.bindUIActionsFields();
},
/**
* Element bindings.
*
* @since 1.7.6
*/
bindUIActionsFields: function() {
app.dragDisable();
$builder
.on( 'wpformsFieldAdd', app.dragDisable )
.on( 'input', '.wpforms-field-option-row-heading input[type="text"]', app.headingUpdates )
.on( 'input', '.wpforms-field-option-row-expanded-description textarea', app.expandedDescriptionUpdates )
.on( 'input', '.wpforms-field-option-row-cta-label input[type="text"]', app.ctaButtonLabelUpdates )
.on( 'input', '.wpforms-field-option-row-cta-link input[type="text"]', app.ctaButtonLinkUpdates )
.on( 'click', '.cta-button.cta-expand-description a', app.showExpandedDescription )
.on( 'focusout', '.wpforms-field-option-row-cta-link input[type="text"]', app.validateCTAlinkField )
.on( 'mousedown', '.wpforms-field-internal-information-checkbox', app.handleCheckboxClick )
.on( 'wpformsDescriptionFieldUpdated', app.descriptionFieldUpdated )
.on( 'wpformsBeforeFieldDeleteAlert', app.preventDeleteFieldAlert )
.on( 'mouseenter', '.internal-information-not-editable .wpforms-field-delete', app.showDismissTitle );
},
/**
* Save checkbox state as a post meta.
*
* @since 1.7.6
*
* @param {string} name Checkbox name.
* @param {int} checked Checkbox state.
*/
saveInternalInformationCheckbox: function( name, checked ) {
$.post(
wpforms_builder.ajax_url,
{
action: 'wpforms_builder_save_internal_information_checkbox',
formId: $( '#wpforms-builder-form' ).data( 'id' ),
name: name,
checked: checked,
nonce: wpforms_builder.nonce,
}
);
},
/**
* Replace checkboxes.
*
* @since 1.7.6
* @since 1.7.9 Added ID parameter.
*
* @param {string} description Expanded description.
* @param {int} id Field ID.
*
* @returns {string} Expanded description with checkboxes HTML.
*/
replaceCheckboxes: function( description, id ) {
const lines = description.split( /\r?\n/ ),
replaced = [],
needle = '[] ';
let lineNumber = -1;
for ( let line of lines ) {
lineNumber++;
line = line.trim();
if ( ! line.startsWith( needle ) ) {
replaced.push( line );
continue;
}
const hash = md5( line ),
name = `iif-${id}-${hash}-${lineNumber}`;
line = line.replace( '[] ', `<div class="wpforms-field-internal-information-checkbox-wrap"><div class="wpforms-field-internal-information-checkbox-input"><input type="checkbox" name="${name}" value="1" class="wpforms-field-internal-information-checkbox" /></div><div class="wpforms-field-internal-information-checkbox-label">` ); line += '</div></div>';
replaced.push( line );
}
return ( wpf.wpautop( replaced.join( '\n' ) ) ).replace( /<br \/>\n$/, '' );
},
/**
* Do not allow field to be draggable.
*
* @since 1.7.9
*/
dragDisable: function() {
WPForms.Admin.Builder.DragFields.fieldDragDisable( $( '.internal-information-not-draggable' ), false );
},
/**
* Real-time updates for "Heading" field option.
*
* @since 1.7.6
*/
headingUpdates: function() {
let $this = $( this ),
value = wpf.sanitizeHTML( $this.val() ),
$head = $( '#wpforms-field-' + $this.parent().data( 'field-id' ) ).find( '.wpforms-field-internal-information-row-heading .heading' );
$head.toggle( value.length !== 0 );
WPFormsBuilder.updateDescription( $head.find( '.text' ), value );
},
/**
* Real-time updates for "Expanded Description" field option.
*
* @since 1.7.6
*/
expandedDescriptionUpdates: function() {
const $this = $( this ),
value = wpf.sanitizeHTML( $this.val() ),
id = $this.parent().data( 'field-id' ),
$field = $( '#wpforms-field-' + id ),
$wrapper = $field.find( '.internal-information-wrap' ),
$buttonContainer = $field.find( '.wpforms-field-internal-information-row-cta-button' ),
$options = $( '#wpforms-field-option-' + id ),
link = $options.find( '.wpforms-field-option-row-cta-link input[type="text"]' ).val(),
label = $options.find( '.wpforms-field-option-row-cta-label input[type="text"]' ).val().length !== 0 ? $options.find( '.wpforms-field-option-row-cta-label input[type="text"]' ).val() : wpforms_builder.empty_label,
$expandable = $wrapper.find( '.wpforms-field-internal-information-row-expanded-description' );
const newLines = app.replaceCheckboxes( value, id );
WPFormsBuilder.updateDescription( $wrapper.find( '.expanded-description' ), newLines );
if ( value.length !== 0 ) { // Expanded description has content.
if ( $expandable.hasClass( 'expanded' ) ) {
return;
}
// Update CTA button.
$buttonContainer.html( app.notExpandedButton() );
return;
}
$expandable.hide().removeClass( 'expanded' );
if ( link.length === 0 ) { // Expanded description does not have value and button has no link.
$buttonContainer.html( '' );
return;
}
$buttonContainer.html( app.standardCtaButton( link, label ) );
},
/**
* Expand additional description on button click.
*
* @since 1.7.6
*
* @param {object} event Click event.
*/
showExpandedDescription: function( event ) {
event.preventDefault();
const $this = $( this ),
id = $this.closest( '.wpforms-field-internal-information' ).data( 'field-id' ),
$expandable = $this.closest( '.internal-information-content' ).find( '.wpforms-field-internal-information-row-expanded-description' ),
$buttonContainer = $( '#wpforms-field-' + id ).find( '.wpforms-field-internal-information-row-cta-button' ),
isExpanded = $expandable.hasClass( 'expanded' );
$expandable.toggleClass( 'expanded' );
if ( ! isExpanded ) {
$expandable.slideDown( 400 );
$buttonContainer.html( app.expandedButton() );
return;
}
$expandable.slideUp( 400 );
$buttonContainer.html( app.notExpandedButton() );
},
/**
* Validate if the CTA Link field has correct url.
*
* @since 1.7.6
*/
validateCTAlinkField: function() {
const $field = $( this ),
url = $field.val().trim();
$field.val( url );
if ( url === '' || wpf.isURL( url ) ) {
return;
}
$.confirm(
{
title: wpforms_builder.heads_up,
content: wpforms_builder.iif_redirect_url_field_error,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: function() {
$field.trigger( 'focus' );
},
},
},
}
);
},
/**
* Handle checkbox checking.
*
* @since 1.7.6
*
* @param {object} event Click event.
*/
handleCheckboxClick: function( event ) {
event.preventDefault();
const $this = $( this ),
checked = ! $this.prop( 'checked' );
$this.prop( 'checked', checked );
app.saveInternalInformationCheckbox( $this.prop( 'name' ), Number( checked ) );
},
/**
* Replace checkboxes on description field.
*
* @since 1.7.6
*
* @param {object} event Triggered event.
* @param {object} data Field element and field value.
*/
descriptionFieldUpdated: function( event, data ) {
const type = $( '#wpforms-field-' + data.id ).data( 'field-type' );
if ( type !== 'internal-information' || data.value.length === 0 ) {
return;
}
data.value = app.replaceCheckboxes( data.value, data.id );
WPFormsBuilder.updateDescription( data.descField, data.value );
},
/**
* Prevent delete field alert to show.
*
* @since 1.7.6
*
* @param {object} event Triggered event.
* @param {object} fieldData Field data.
* @param {string} type Field type.
*/
preventDeleteFieldAlert: function( event, fieldData, type ) {
if ( type === 'internal-information' ) {
event.preventDefault();
WPFormsBuilder.fieldDeleteById( fieldData.id, type, 50 );
}
},
/**
* Replace Delete field button title with Dismiss.
*
* @since 1.7.6
*/
showDismissTitle: function() {
$( this ).attr( 'title', wpforms_builder.iif_dismiss );
},
/**
* Real-time updates for "CTA button" link.
*
* @since 1.7.6
*/
ctaButtonLinkUpdates() {
let $this = $( this ),
id = $this.parent().data( 'field-id' ),
$field = $( '#wpforms-field-' + id ),
$buttonContainer = $field.find( '.wpforms-field-internal-information-row-cta-button' ),
$expandable = $field.find( '.wpforms-field-internal-information-row-expanded-description' ),
desc = $this.closest( '#wpforms-field-option-' + id ).find( '.wpforms-field-option-row-expanded-description textarea' ).val(),
label = $this.closest( '#wpforms-field-option-' + id ).find( '.wpforms-field-option-row-cta-label input[type="text"]' ).val();
if ( desc.length !== 0 ) {
if ( $expandable.hasClass( 'expanded' ) ) {
$buttonContainer.html( app.expandedButton() );
return;
}
$buttonContainer.html( app.notExpandedButton() );
return;
}
if ( wpf.isURL( $this.val() ) && label.length !== 0 ) {
$buttonContainer.html( app.standardCtaButton( $this.val(), label ) );
return;
}
$buttonContainer.html( '' );
},
/**
* Real-time updates for "CTA button" label.
*
* @since 1.7.6
*/
ctaButtonLabelUpdates: function() {
let $this = $( this ),
value = wpf.sanitizeHTML( $this.val() ),
id = $this.parent().data( 'field-id' ),
$field = $( '#wpforms-field-' + id ),
$buttonContainer = $field.find( '.wpforms-field-internal-information-row-cta-button' ),
$expandable = $field.find( '.wpforms-field-internal-information-row-expanded-description' ),
desc = $this.closest( '#wpforms-field-option-' + id ).find( '.wpforms-field-option-row-expanded-description textarea' ).val(),
link = $this.closest( '#wpforms-field-option-' + id ).find( '.wpforms-field-option-row-cta-link input[type="text"]' ).val();
if ( desc.length !== 0 && value.length !== 0 ) {
if ( $expandable.hasClass( 'expanded' ) ) {
$buttonContainer.html( app.expandedButton() );
return;
}
$buttonContainer.html( app.notExpandedButton() );
return;
}
if ( value.length !== 0 && wpf.isURL( link ) ) {
$buttonContainer.html( app.standardCtaButton( link, value ) );
return;
}
if ( desc.length === 0 ) {
$buttonContainer.html( '' );
}
},
/**
* Standard CTA button template.
*
* @since 1.7.6
*
* @param {string} url Button URL.
* @param {string} label Button label.
*
* @returns {string} Button HTML.
*/
standardCtaButton: function( url, label ) {
let button = `<div class="cta-button cta-link-external ">
<a href="%url%" target="_blank" rel="noopener noreferrer">
<span class="button-label">%label%</span>
</a></div>`;
return button.replace( '%url%', wpf.sanitizeHTML( url ) ).replace( '%label%', wpf.sanitizeHTML( label ) );
},
/**
* Not expanded button.
*
* @since 1.7.6
*
* @returns {string} Not expanded button HTML.
*/
notExpandedButton: function() {
let button = `<div class="cta-button cta-expand-description not-expanded">
<a href="#" target="_blank" rel="noopener noreferrer">
<span class="button-label">%label%</span>
<span class="icon not-expanded">
<svg viewBox="0 0 10 7">
<path d="M4.91016 5.90234C5.15625 6.14844 5.56641 6.14844 5.8125 5.90234L9.53125 2.18359C9.80469 1.91016 9.80469 1.5 9.53125 1.25391L8.92969 0.625C8.65625 0.378906 8.24609 0.378906 8 0.625L5.34766 3.27734L2.72266 0.625C2.47656 0.378906 2.06641 0.378906 1.79297 0.625L1.19141 1.25391C0.917969 1.5 0.917969 1.91016 1.19141 2.18359L4.91016 5.90234Z"></path>
<path d="M4.91016 5.90234C5.15625 6.14844 5.56641 6.14844 5.8125 5.90234L9.53125 2.18359C9.80469 1.91016 9.80469 1.5 9.53125 1.25391L8.92969 0.625C8.65625 0.378906 8.24609 0.378906 8 0.625L5.34766 3.27734L2.72266 0.625C2.47656 0.378906 2.06641 0.378906 1.79297 0.625L1.19141 1.25391C0.917969 1.5 0.917969 1.91016 1.19141 2.18359L4.91016 5.90234Z"></path>
</svg>
</span>
</a></div>`;
return button.replace( '%label%', wpforms_builder.iif_more );
},
/**
* Expanded button.
*
* @since 1.7.6
*
* @returns {string} Expanded button HTML.
*/
expandedButton: function() {
let button = `<div class="cta-button cta-expand-description expanded">
<a href="#" target="_blank" rel="noopener noreferrer">
<span class="button-label">%label%</span>
<span class="icon expanded">
<svg viewBox="0 0 10 7">
<path d="M5.83984 0.625C5.56641 0.378906 5.15625 0.378906 4.91016 0.625L1.19141 4.34375C0.917969 4.61719 0.917969 5.02734 1.19141 5.27344L1.79297 5.90234C2.06641 6.14844 2.47656 6.14844 2.72266 5.90234L5.375 3.25L8 5.90234C8.24609 6.14844 8.68359 6.14844 8.92969 5.90234L9.55859 5.27344C9.80469 5.02734 9.80469 4.61719 9.55859 4.34375L5.83984 0.625Z" fill="red"></path>
</svg>
</span>
</a></div>`;
return button.replace( '%label%', wpforms_builder.close );
},
};
return app;
}( document, window, jQuery ) );
WPFormsInternalInformationField.init();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,788 @@
/* global List, wpforms_form_templates, wpforms_addons, wpf, WPFormsUtils */
/**
* @param wpforms_form_templates.admin_nonce
* @param wpforms_form_templates.delete_template
* @param wpforms_form_templates.delete_template_content
* @param wpforms_form_templates.delete_template_title
* @param wpforms_form_templates.template_addon_activate
* @param wpforms_form_templates.template_addon_prompt
* @param wpforms_form_templates.template_addons_error
* @param wpforms_form_templates.template_addons_prompt
* @param wpforms_form_templates.use_template
*/
// noinspection ES6ConvertVarToLetConst
/**
* Form Templates function.
*
* @since 1.7.7
*/
// eslint-disable-next-line no-var
var WPFormsFormTemplates = window.WPFormsFormTemplates || ( function( document, window, $ ) {
/**
* Runtime variables.
*
* @since 1.7.7
*
* @type {Object}
*/
const vars = {};
/**
* Public functions and properties.
*
* @since 1.7.7
*
* @type {Object}
*/
const app = {
/**
* Start the engine.
*
* @since 1.7.7
*/
init() {
$( app.ready );
$( window ).on( 'load', function() {
// in the case of jQuery 3.+ we need to wait for the `ready` event first.
if ( typeof $.ready.then === 'function' ) {
$.ready.then( app.load );
} else {
app.load();
}
} );
},
/**
* Document ready.
*
* @since 1.7.7
*/
ready() {
app.events();
},
/**
* Window load.
*
* @since 1.7.7
*/
load() {
app.showUpgradeBanner();
},
/**
* Setup. Prepare some variables.
*
* @since 1.7.7
*/
setup() {
// Trigger event before initializing the template list.
WPFormsUtils.triggerEvent( $( document ), 'wpformsSetupPanelBeforeInitTemplatesList' );
// Template list object.
vars.templateList = new List( 'wpforms-setup-templates-list', {
valueNames: [
'wpforms-template-name',
'wpforms-template-desc',
{
name: 'fields',
attr: 'data-fields',
},
{
name: 'slug',
attr: 'data-slug',
},
{
name: 'categories',
attr: 'data-categories',
},
{
name: 'subcategories',
attr: 'data-subcategories',
},
{
name: 'has-access',
attr: 'data-has-access',
},
{
name: 'favorite',
attr: 'data-favorite',
},
],
} );
},
/**
* Bind events.
*
* @since 1.7.7
*/
events() {
$( document )
.on( 'click', '#wpforms-setup-templates-list .wpforms-template-favorite i', app.selectFavorite )
.on( 'click', '#wpforms-setup-templates-list .wpforms-template-remove i', app.removeTemplate );
},
/**
* Select Favorite Templates.
*
* @since 1.7.7
*/
// eslint-disable-next-line max-lines-per-function
selectFavorite() {
const $heartIcon = $( this ),
favorite = $heartIcon.hasClass( 'fa-heart-o' ),
$favorite = $heartIcon.closest( '.wpforms-template-favorite' ),
$template = $heartIcon.closest( '.wpforms-template' ),
$templateName = $template.find( '.wpforms-template-name' ),
templateSlug = $template.find( '.wpforms-template-select' ).data( 'slug' ),
$favoritesCategory = $( '.wpforms-setup-templates-categories' ).find( '[data-category=\'favorites\']' ),
$favoritesCount = $favoritesCategory.find( 'span' ),
data = {
action: 'wpforms_templates_favorite',
slug: templateSlug,
favorite,
nonce: wpforms_form_templates.nonce,
};
let favoritesCount = parseInt( $favoritesCount.html(), 10 );
const item = vars.templateList.get( 'slug', templateSlug )[ 0 ],
values = item.values();
const toggleHeartIcon = function() {
$favorite.find( '.fa-heart-o' ).toggleClass( 'wpforms-hidden', values.favorite );
$favorite.find( '.fa-heart' ).toggleClass( 'wpforms-hidden', ! values.favorite );
};
const unMarkFavorite = function() {
values.favorite = false;
favoritesCount = favoritesCount - 1;
item.values( values );
toggleHeartIcon();
$templateName.data( 'data-favorite', 0 );
$favoritesCount.html( favoritesCount );
app.maybeHideFavoritesCategory();
};
const markFavorite = function() {
values.favorite = true;
favoritesCount = favoritesCount + 1;
item.values( values );
toggleHeartIcon();
$templateName.data( 'data-favorite', 1 );
$favoritesCount.html( favoritesCount );
app.maybeHideFavoritesCategory();
};
$.post( wpforms_form_templates.ajaxurl, data, function( res ) {
if ( ! res.success ) {
if ( favorite ) {
unMarkFavorite();
return;
}
markFavorite();
}
} );
if ( favorite ) {
markFavorite();
return;
}
unMarkFavorite();
},
/**
* Remove Template.
*
* @since 1.8.8
*/
removeTemplate() {
const $trashIcon = $( this ),
$template = $trashIcon.closest( '.wpforms-template-remove' ),
$templateId = $template.data( 'template' );
$.alert( {
title: wpforms_form_templates.delete_template_title,
content: wpforms_form_templates.delete_template_content,
icon: 'fa fa-exclamation-circle',
type: 'red',
buttons: {
confirm: {
text: wpforms_form_templates.delete_template,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
app.removeUserTemplate( $templateId );
},
},
cancel: {
text: wpforms_form_templates.cancel,
},
},
} );
},
/**
* Remove User Template.
*
* @since 1.8.8
*
* @param {number} templateId Template ID.
*/
removeUserTemplate( templateId ) {
vars.templateList.remove( 'slug', 'wpforms-user-template-' + templateId );
$.post( wpforms_form_templates.ajaxurl, {
action: 'wpforms_user_template_remove',
template: templateId,
nonce: wpforms_form_templates.nonce,
}, function( res ) {
if ( res.success ) {
$( '#wpforms-template-wpforms-user-template-' + templateId ).remove();
app.updateCategoryCount( 'all' );
app.updateCategoryCount( 'user' );
}
} );
},
/**
* Update category count.
*
* @since 1.8.8
*
* @param {string} category Category name.
*/
updateCategoryCount( category ) {
const categoriesList = $( '.wpforms-setup-templates-categories' ),
$category = categoriesList.find( `[data-category='${ category }']` ),
$count = $category.find( 'span' ),
count = parseInt( $count.html(), 10 );
$count.html( count - 1 );
$category.data( 'count', count - 1 );
if ( count - 1 === 0 && category === 'user' && $category.hasClass( 'active' ) ) {
$( '.wpforms-user-templates-empty-state' ).removeClass( 'wpforms-hidden' );
}
},
/**
* Maybe hide favorites category if there are no templates.
*
* @since 1.7.7
*/
maybeHideFavoritesCategory() {
const $categoriesList = $( '.wpforms-setup-templates-categories' ),
$favoritesCategory = $categoriesList.find( '[data-category=\'favorites\']' ),
favoritesCount = parseInt( $favoritesCategory.find( 'span' ).html(), 10 );
$favoritesCategory.toggleClass( 'wpforms-hidden', ! favoritesCount );
if ( $favoritesCategory.hasClass( 'active' ) ) {
if ( ! favoritesCount ) {
$categoriesList.find( '[data-category=\'all\']' ).trigger( 'click' );
return;
}
$favoritesCategory.trigger( 'click' );
}
},
/**
* Search template callback.
*
* @since 1.7.7
*/
searchTemplate() {
app.performSearch( $( this ).val() );
app.showUpgradeBanner();
},
/**
* Perform search value.
*
* @since 1.7.7.2
*
* @param {string} query Value to search.
*/
performSearch( query ) {
const searchResult = vars.templateList.search( query, [ 'name' ], function( searchString ) {
for ( let index = 0, length = vars.templateList.items.length; index < length; index++ ) {
const values = vars.templateList.items[ index ].values();
const templateName = values[ 'wpforms-template-name' ].toLowerCase();
const templateDesc = values[ 'wpforms-template-desc' ].toLowerCase();
const fields = values.fields.toLowerCase();
const searchRegex = new RegExp( searchString );
vars.templateList.items[ index ].found = searchRegex.test( templateName ) || searchRegex.test( templateDesc ) || searchRegex.test( fields );
}
} );
$( '.wpforms-templates-no-results' ).toggle( ! searchResult.length );
},
/**
* Select subcategory.
*
* @since 1.8.4
*
* @param {Object} e Event object.
*/
selectSubCategory( e ) {
e.preventDefault();
const $item = $( this );
const $activeCategory = $item.parent( 'ul' ).parent( 'li' ).parent( 'ul' ).children( 'li.active' );
const $activeSubcategory = $( '.wpforms-setup-templates-subcategories li.active' );
const subcategory = $item.data( 'subcategory' );
const category = $item.parents( 'li' ).data( 'category' );
const searchQuery = $( '#wpforms-setup-template-search' ).val();
// Clear active class from the parent category and current subcategory.
$activeSubcategory.removeClass( 'active' );
$activeCategory.removeClass( 'active' );
// Add active class to the parent category and current subcategory.
$item.parents( 'li' ).addClass( 'active' );
$item.addClass( 'active' );
vars.templateList.filter( function( item ) {
return category === 'all' || ( item.values().categories.split( ',' ).indexOf( category ) > -1 && item.values().subcategories.split( ',' ).indexOf( subcategory ) > -1 );
} );
if ( searchQuery !== '' ) {
app.performSearch( searchQuery );
}
app.showUpgradeBanner();
},
/**
* Select category.
*
* @since 1.7.7
*
* @param {Object} e Event object.
*/
selectCategory( e ) {
e.preventDefault();
const $item = $( this ).parent(),
$active = $item.closest( 'ul' ).find( '.active' ),
category = $item.data( 'category' ),
count = $item.data( 'count' ),
searchQuery = $( '#wpforms-setup-template-search' ).val();
$active.removeClass( 'active' );
$item.addClass( 'active opened' );
vars.templateList.filter( function( item ) {
if ( category === 'available' ) {
return item.values()[ 'has-access' ];
}
if ( category === 'favorites' ) {
return item.values().favorite;
}
return category === 'all' || item.values().categories.split( ',' ).indexOf( category ) > -1;
} );
// Display/hide User Templates empty state message.
$( '.wpforms-user-templates-empty-state' ).toggleClass( 'wpforms-hidden', category !== 'user' || count !== 0 );
if ( searchQuery !== '' ) {
app.performSearch( searchQuery );
}
app.showUpgradeBanner();
},
/**
* Show/hide the subcategory list by clicking on the chevron icon.
*
* @since 1.8.7
*
* @param {Object} e Event object.
*/
toggleSubcategoriesList( e ) {
e.stopPropagation();
const $item = $( this ).parent().parent();
$item.toggleClass( 'opened' );
},
/**
* Cancel button click routine.
*
* @since 1.7.7
*/
selectTemplateCancel( ) {
const $template = $( '#wpforms-setup-templates-list' ).find( '.wpforms-template.active' ),
$button = $template.find( '.wpforms-template-select' );
$template.removeClass( 'active' );
$button.html( $button.data( 'labelOriginal' ) );
},
/**
* Show upgrade banner if a license type is less than Pro.
*
* @since 1.7.7
*/
showUpgradeBanner() {
if ( ! $( '#tmpl-wpforms-templates-upgrade-banner' ).length ) {
return;
}
const template = wp.template( 'wpforms-templates-upgrade-banner' );
if ( ! template ) {
return;
}
const $templates = $( '#wpforms-setup-templates-list .wpforms-template' );
if ( $templates.length > 5 ) {
$templates.eq( 5 ).after( template() );
return;
}
$templates.last().after( template() );
},
/**
* Select template.
*
* @since 1.8.2
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {jQuery} $button Use a template button object.
* @param {Function} callback The function to set the template.
*/
selectTemplateProcess( formName, template, $button, callback ) {
if ( $button.data( 'addons' ) ) {
app.addonsModal( formName, template, $button, callback );
return;
}
callback( formName, template );
},
/**
* Open required addons alert.
*
* @since 1.8.2
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {jQuery} $button Use a template button object.
* @param {Function} callback The function to set the template.
*/
addonsModal( formName, template, $button, callback ) {
const templateName = $button.data( 'template-name-raw' );
const addonsNames = $button.data( 'addons-names' );
const addonsSlugs = $button.data( 'addons' );
const installedSlugs = $button.data( 'installed' );
const addons = addonsSlugs.split( ',' );
let prompt;
switch ( app.action( addons, installedSlugs ) ) {
case 'multiple':
prompt = wpforms_form_templates.template_addons_prompt;
break;
case 'activate':
prompt = wpforms_form_templates.template_addon_activate;
break;
case 'install':
prompt = wpforms_form_templates.template_addon_prompt;
break;
default:
prompt = wpforms_form_templates.template_addons_prompt;
break;
}
prompt = prompt.replace( /%template%/g, templateName ).replace( /%addons%/g, addonsNames );
if ( ! addons.length ) {
return;
}
if ( ! wpforms_form_templates.can_install_addons ) {
app.userCannotInstallAddonsModal( prompt );
return;
}
app.userCanInstallAddonsModal( formName, template, addons, prompt, callback, installedSlugs );
},
/**
* Open the template addon alert for admins.
*
* @since 1.8.2
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {Array} addons Array of addon slugs.
* @param {string} prompt Modal content.
* @param {Function} callback The function to set the template.
* @param {string} installedSlugs Installed slug.
*/
userCanInstallAddonsModal( formName, template, addons, prompt, callback, installedSlugs = '' ) {
const spinner = '<i class="wpforms-loading-spinner wpforms-loading-white wpforms-loading-inline"></i>';
let confirm;
switch ( app.action( addons, installedSlugs ) ) {
case 'multiple':
case 'install':
confirm = wpforms_form_templates.install_confirm;
break;
case 'activate':
confirm = wpforms_form_templates.activate_confirm;
break;
default:
confirm = wpforms_form_templates.install_confirm;
break;
}
$.confirm( {
title: wpforms_form_templates.heads_up,
content: prompt,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: confirm,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
this.$$confirm
.prop( 'disabled', true )
.html( spinner + wpforms_form_templates.activating );
this.$$cancel
.prop( 'disabled', true );
app.installActivateAddons( addons, this, formName, template, callback );
return false;
},
},
cancel: {
text: wpforms_form_templates.cancel,
action() {
WPFormsFormTemplates.selectTemplateCancel();
},
},
},
} );
},
/**
* Get the action for the addons.
*
* @since 1.9.0
*
* @param {Array} addons Addons slugs.
* @param {string} installed Installed addon slug.
*
* @return {string} Action.
*/
action( addons, installed = '' ) {
if ( addons.length > 1 ) {
return 'multiple';
}
if ( installed.split( ',' ).indexOf( addons[ 0 ] ) > -1 ) {
return 'activate';
}
return 'install';
},
/**
* Open the template addon alert for non-admins.
*
* @since 1.8.2
*
* @param {string} prompt Modal content.
*/
userCannotInstallAddonsModal( prompt ) {
$.alert( {
title: wpforms_form_templates.heads_up,
content: prompt,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
ok: {
text: wpforms_form_templates.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
WPFormsFormTemplates.selectTemplateCancel();
},
},
},
} );
},
/**
* Install & Activate addons via AJAX.
*
* @since 1.8.2
*
* @param {Array} addons Addons slugs.
* @param {Object} previousModal Previous modal instance.
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {Function} callback The function to set the template.
*/
installActivateAddons( addons, previousModal, formName, template, callback ) {
const ajaxResults = [];
const ajaxErrors = [];
let promiseChain = false;
// Put each of the ajax call promises to the chain.
addons.forEach( function( addon ) {
if ( typeof promiseChain.done !== 'function' ) {
promiseChain = app.installActivateAddonAjax( addon );
return;
}
promiseChain = promiseChain
.done( function( value ) {
ajaxResults.push( value );
return app.installActivateAddonAjax( addon );
} )
.fail( function( error ) {
ajaxErrors.push( error );
} );
} );
promiseChain
// Latest promise result and error.
.done( function( value ) {
ajaxResults.push( value );
} )
.fail( function( error ) {
ajaxErrors.push( error );
} )
// Finally, resolve all the promises.
.always( function() {
previousModal.close();
if (
ajaxResults.length > 0 &&
wpf.listPluck( ajaxResults, 'success' ).every( Boolean ) && // Check if every `success` is true.
ajaxErrors.length === 0
) {
callback( formName, template );
return;
}
app.installActivateAddonsError( formName, template, callback );
} );
},
/**
* Install & Activate addons error modal.
*
* @since 1.8.2
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {Function} callback The function to set the template.
*/
installActivateAddonsError( formName, template, callback ) {
$.confirm( {
title: wpforms_form_templates.heads_up,
content: wpforms_form_templates.template_addons_error,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_form_templates.use_template,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
callback( formName, template );
},
},
cancel: {
text: wpforms_form_templates.cancel,
action() {
app.selectTemplateCancel();
},
},
},
} );
},
/**
* Install & Activate single addon via AJAX.
*
* @since 1.8.2
*
* @param {string} addon Addon slug.
*
* @return {Promise} jQuery ajax call promise.
*/
installActivateAddonAjax( addon ) {
const addonData = wpforms_addons[ addon ];
const deferred = new $.Deferred();
if (
! addonData ||
[ 'activate', 'install' ].indexOf( addonData.action ) < 0
) {
deferred.resolve( false );
return deferred.promise();
}
return $.post(
wpforms_form_templates.ajaxurl,
{
action: 'wpforms_' + addonData.action + '_addon',
nonce: wpforms_form_templates.admin_nonce,
plugin: addonData.action === 'activate' ? addon + '/' + addon + '.php' : addonData.url,
}
);
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPFormsFormTemplates.init();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,550 @@
/* global wpforms_builder_help, wpf */
/**
* WPForms Builder Help screen module.
*
* @since 1.6.3
*/
'use strict';
var WPForms = window.WPForms || {};
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.Help = WPForms.Admin.Builder.Help || ( function( document, window, $ ) {
/**
* Elements holder.
*
* @since 1.6.3
*
* @type {object}
*/
var el;
/**
* UI functions.
*
* @since 1.6.3
*
* @type {object}
*/
var ui;
/**
* Event handlers.
*
* @since 1.6.3
*
* @type {object}
*/
var event;
/**
* Public functions and properties.
*
* @since 1.6.3
*
* @type {object}
*/
var app = {
/**
* Start the engine. DOM is not ready yet, use only to init something.
*
* @since 1.6.3
*/
init: function() {
$( app.ready );
},
/**
* DOM is fully loaded.
*
* @since 1.6.3
*/
ready: function() {
app.setup();
app.initCategories();
app.events();
},
/**
* Setup. Prepare some variables.
*
* @since 1.6.3
*/
setup: function() {
// Cache DOM elements.
el = {
$builder: $( '#wpforms-builder' ),
$builderForm: $( '#wpforms-builder-form' ),
$helpBtn: $( '#wpforms-help' ),
$help: $( '#wpforms-builder-help' ),
$closeBtn: $( '#wpforms-builder-help-close' ),
$search: $( '#wpforms-builder-help-search' ),
$result: $( '#wpforms-builder-help-result' ),
$noResult: $( '#wpforms-builder-help-no-result' ),
$categories: $( '#wpforms-builder-help-categories' ),
$footer: $( '#wpforms-builder-help-footer' ),
};
},
/**
* Bind events.
*
* @since 1.6.3
*/
events: function() {
// Open/close help modal.
el.$helpBtn.on( 'click', event.openHelp );
el.$closeBtn.on( 'click', event.closeHelp );
// Expand/collapse category.
el.$categories.on( 'click', '.wpforms-builder-help-category header', event.toggleCategory );
// View all Category Docs button click.
el.$categories.on( 'click', '.wpforms-builder-help-category button.viewall', event.viewAllCategoryDocs );
// Input into search field.
el.$search.on( 'keyup', 'input', _.debounce( event.inputSearch, 250 ) );
// Clear search field.
el.$search.on( 'click', '#wpforms-builder-help-search-clear', event.clearSearch );
},
/**
* Init (generate) categories list.
*
* @since 1.6.3
*/
initCategories: function() {
// Display error if docs data is not available.
if ( wpf.empty( wpforms_builder_help.docs ) ) {
el.$categories.html( wp.template( 'wpforms-builder-help-categories-error' ) );
return;
}
var tmpl = wp.template( 'wpforms-builder-help-categories' ),
data = {
categories: wpforms_builder_help.categories,
docs: app.getDocsByCategories(),
};
el.$categories.html( tmpl( data ) );
},
/**
* Init categories list.
*
* @since 1.6.3
*
* @returns {object} Docs arranged by category.
*/
getDocsByCategories: function() {
var categories = wpforms_builder_help.categories,
docs = wpforms_builder_help.docs || [],
docsByCategories = {};
_.each( categories, function( categoryTitle, categorySlug ) {
var docsByCategory = [];
_.each( docs, function( doc ) {
if ( doc.categories && doc.categories.indexOf( categorySlug ) > -1 ) {
docsByCategory.push( doc );
}
} );
docsByCategories[ categorySlug ] = docsByCategory;
} );
return docsByCategories;
},
/**
* Get docs recommended by search term.
*
* @since 1.6.3
*
* @param {string} term Search term.
*
* @returns {Array} Recommended docs.
*/
getRecommendedDocs: function( term ) {
if ( wpf.empty( term ) ) {
return [];
}
term = term.toLowerCase();
var docs = wpforms_builder_help.docs,
recommendedDocs = [];
if ( wpf.empty( wpforms_builder_help.context.docs[ term ] ) ) {
return [];
}
_.each( wpforms_builder_help.context.docs[ term ], function( docId ) {
if ( ! wpf.empty( docs[ docId ] ) ) {
recommendedDocs.push( docs[ docId ] );
}
} );
return recommendedDocs;
},
/**
* Get docs filtered by search term.
*
* @since 1.6.3
*
* @param {string} term Search term.
*
* @returns {Array} Filtered docs.
*/
getFilteredDocs: function( term ) {
if ( wpf.empty( term ) ) {
return [];
}
var docs = wpforms_builder_help.docs,
filteredDocs = [];
term = term.toLowerCase();
_.each( docs, function( doc ) {
if ( doc.title && doc.title.toLowerCase().indexOf( term ) > -1 ) {
filteredDocs.push( doc );
}
} );
return filteredDocs;
},
/**
* Get the current context (state) of the form builder.
*
* @since 1.6.3
*
* @returns {string} Builder context string. For example 'fields/add_field' or 'settings/notifications'.
*/
getBuilderContext: function() {
// New (not saved) form.
if ( wpf.empty( el.$builderForm.data( 'id' ) ) ) {
return 'new_form';
}
// Determine builder panel and section.
var panel = el.$builder.find( '#wpforms-panels-toggle button.active' ).data( 'panel' ),
$panel = el.$builder.find( '#wpforms-panel-' + panel ),
section = '',
subsection = '',
context;
switch ( panel ) {
case 'fields':
section = $panel.find( '.wpforms-panel-sidebar .wpforms-tab a.active' ).parent().attr( 'id' );
break;
case 'setup':
section = '';
break;
default:
section = $panel.find( '.wpforms-panel-sidebar a.active' ).data( 'section' );
}
section = ! wpf.empty( section ) ? section.replace( /-/g, '_' ) : '';
// Detect field type.
if ( section === 'field_options' ) {
subsection = $panel.find( '#wpforms-field-options .wpforms-field-option:visible .wpforms-field-option-hidden-type' ).val();
}
// Combine to context array.
context = [ panel, section, subsection ].filter( function( el ) {
return ! wpf.empty( el ) && el !== 'default';
} );
// Return imploded string.
return context.join( '/' );
},
/**
* Get the search term for the current builder context.
*
* @since 1.6.3
*
* @returns {string} Builder context term string.
*/
getBuilderContextTerm: function() {
return wpforms_builder_help.context.terms[ app.getBuilderContext() ] || '';
},
};
/**
* UI functions.
*/
ui = {
/**
* Configuration.
*
* @since 1.6.3
*
* @type {object}
*/
config: {
speed: 300, // Fading/sliding duration in milliseconds.
},
/**
* Display the element by fading them to opaque using CSS.
*
* @since 1.6.3
*
* @param {jQuery} $el Element object.
*/
fadeIn: function( $el ) {
if ( ! $el.length ) {
return;
}
$el.css( {
display: '',
transition: `opacity ${ui.config.speed}ms ease-in 0s`,
} );
setTimeout( function() {
$el.css( 'opacity', '1' );
}, 0 );
},
/**
* Hide the element by fading them to transparent using CSS.
*
* @since 1.6.3
*
* @param {jQuery} $el Element object.
*/
fadeOut: function( $el ) {
if ( ! $el.length ) {
return;
}
$el.css( {
opacity: '0',
transition: `opacity ${ui.config.speed}ms ease-in 0s`,
} );
setTimeout( function() {
$el.css( 'display', 'none' );
}, ui.config.speed );
},
/**
* Collapse all categories.
*
* @since 1.6.3
*/
collapseAllCategories: function() {
el.$categories.find( '.wpforms-builder-help-category' ).removeClass( 'opened' );
el.$categories.find( '.wpforms-builder-help-docs' ).slideUp();
},
};
/**
* Event handlers.
*/
event = {
/**
* Open help modal.
*
* @since 1.6.3
*
* @param {object} e Event object.
*/
openHelp: function( e ) {
e.preventDefault();
var $firstCategory = el.$categories.find( '.wpforms-builder-help-category' ).first(),
builderContextTerm = app.getBuilderContextTerm();
if ( builderContextTerm === '' && ! $firstCategory.hasClass( 'opened' ) ) {
$firstCategory.find( 'header' ).first().trigger( 'click' );
} else {
ui.collapseAllCategories();
}
el.$search.find( 'input' ).val( builderContextTerm ).trigger( 'keyup' );
ui.fadeIn( el.$help );
setTimeout( function() {
ui.fadeIn( el.$result );
ui.fadeIn( el.$categories );
ui.fadeIn( el.$footer );
}, ui.config.speed );
},
/**
* Close help modal.
*
* @since 1.6.3
*
* @param {object} e Event object.
*/
closeHelp: function( e ) {
e.preventDefault();
ui.fadeOut( el.$result );
ui.fadeOut( el.$categories );
ui.fadeOut( el.$footer );
ui.fadeOut( el.$help );
},
/**
* Toggle category.
*
* @since 1.6.3
*
* @param {object} e Event object.
*/
toggleCategory: function( e ) {
var $category = $( this ).parent(),
$categoryDocs = $category.find( '.wpforms-builder-help-docs' );
if ( ! $categoryDocs.is( ':visible' ) ) {
$category.addClass( 'opened' );
} else {
$category.removeClass( 'opened' );
}
$categoryDocs.stop().slideToggle( ui.config.speed );
},
/**
* View All Category Docs button click.
*
* @since 1.6.3
*
* @param {object} e Event object.
*/
viewAllCategoryDocs: function( e ) {
var $btn = $( this );
$btn.prev( 'div' ).stop().slideToggle( ui.config.speed, function() {
$btn.closest( '.wpforms-builder-help-category' ).addClass( 'viewall' );
} );
ui.fadeOut( $btn );
$btn.slideUp();
},
/**
* Input into search field.
*
* @since 1.6.3
*
* @param {object} e Event object.
*/
inputSearch: function( e ) {
var $input = $( this ),
term = $input.val();
var tmpl = wp.template( 'wpforms-builder-help-docs' ),
recommendedDocs = app.getRecommendedDocs( term ),
filteredDocs = event.removeDuplicates( recommendedDocs, app.getFilteredDocs( term ) ),
resultHTML = '';
el.$search.toggleClass( 'wpforms-empty', ! term );
if ( ! wpf.empty( recommendedDocs ) ) {
resultHTML += tmpl( {
docs: recommendedDocs,
} );
}
if ( ! wpf.empty( filteredDocs ) ) {
resultHTML += tmpl( {
docs: filteredDocs,
} );
}
el.$noResult.toggle( resultHTML === '' && term !== '' );
el.$result.html( resultHTML );
el.$help[0].scrollTop = 0;
},
/**
* Remove duplicated items in the filtered docs.
*
* @since 1.6.3
*
* @param {Array} recommendedDocs Recommended docs.
* @param {Array} filteredDocs Filtered docs.
*
* @returns {Array} Filtered docs without duplicated items in the recommended docs.
*/
removeDuplicates: function( recommendedDocs, filteredDocs ) {
if ( wpf.empty( recommendedDocs ) || wpf.empty( filteredDocs ) ) {
return filteredDocs;
}
var docs = [];
for ( var i = 0; i < recommendedDocs.length, i++; ) {
for ( var k = 0; k < filteredDocs.length, k++; ) {
if ( filteredDocs[ k ].url !== recommendedDocs[ i ].url ) {
docs.push( filteredDocs[ k ] );
}
}
}
return docs;
},
/**
* Clear search field.
*
* @since 1.6.3
*
* @param {object} e Event object.
*/
clearSearch: function( e ) {
el.$search.find( 'input' ).val( '' ).trigger( 'keyup' );
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.Help.init();

View File

@@ -0,0 +1 @@
"use strict";var WPForms=window.WPForms||{};WPForms.Admin=WPForms.Admin||{},WPForms.Admin.Builder=WPForms.Admin.Builder||{},WPForms.Admin.Builder.Help=WPForms.Admin.Builder.Help||function(l){var n,p={init:function(){l(p.ready)},ready:function(){p.setup(),p.initCategories(),p.events()},setup:function(){n={$builder:l("#wpforms-builder"),$builderForm:l("#wpforms-builder-form"),$helpBtn:l("#wpforms-help"),$help:l("#wpforms-builder-help"),$closeBtn:l("#wpforms-builder-help-close"),$search:l("#wpforms-builder-help-search"),$result:l("#wpforms-builder-help-result"),$noResult:l("#wpforms-builder-help-no-result"),$categories:l("#wpforms-builder-help-categories"),$footer:l("#wpforms-builder-help-footer")}},events:function(){n.$helpBtn.on("click",a.openHelp),n.$closeBtn.on("click",a.closeHelp),n.$categories.on("click",".wpforms-builder-help-category header",a.toggleCategory),n.$categories.on("click",".wpforms-builder-help-category button.viewall",a.viewAllCategoryDocs),n.$search.on("keyup","input",_.debounce(a.inputSearch,250)),n.$search.on("click","#wpforms-builder-help-search-clear",a.clearSearch)},initCategories:function(){var e,r;wpf.empty(wpforms_builder_help.docs)?n.$categories.html(wp.template("wpforms-builder-help-categories-error")):(e=wp.template("wpforms-builder-help-categories"),r={categories:wpforms_builder_help.categories,docs:p.getDocsByCategories()},n.$categories.html(e(r)))},getDocsByCategories:function(){var e=wpforms_builder_help.categories,o=wpforms_builder_help.docs||[],i={};return _.each(e,function(e,r){var t=[];_.each(o,function(e){e.categories&&-1<e.categories.indexOf(r)&&t.push(e)}),i[r]=t}),i},getRecommendedDocs:function(e){if(wpf.empty(e))return[];e=e.toLowerCase();var r=wpforms_builder_help.docs,t=[];return wpf.empty(wpforms_builder_help.context.docs[e])?[]:(_.each(wpforms_builder_help.context.docs[e],function(e){wpf.empty(r[e])||t.push(r[e])}),t)},getFilteredDocs:function(r){var e,t;return wpf.empty(r)?[]:(e=wpforms_builder_help.docs,t=[],r=r.toLowerCase(),_.each(e,function(e){e.title&&-1<e.title.toLowerCase().indexOf(r)&&t.push(e)}),t)},getBuilderContext:function(){if(wpf.empty(n.$builderForm.data("id")))return"new_form";var e=n.$builder.find("#wpforms-panels-toggle button.active").data("panel"),r=n.$builder.find("#wpforms-panel-"+e),t="",o="";switch(e){case"fields":t=r.find(".wpforms-panel-sidebar .wpforms-tab a.active").parent().attr("id");break;case"setup":t="";break;default:t=r.find(".wpforms-panel-sidebar a.active").data("section")}return[e,t=wpf.empty(t)?"":t.replace(/-/g,"_"),o="field_options"===t?r.find("#wpforms-field-options .wpforms-field-option:visible .wpforms-field-option-hidden-type").val():o].filter(function(e){return!wpf.empty(e)&&"default"!==e}).join("/")},getBuilderContextTerm:function(){return wpforms_builder_help.context.terms[p.getBuilderContext()]||""}},o={config:{speed:300},fadeIn:function(e){e.length&&(e.css({display:"",transition:`opacity ${o.config.speed}ms ease-in 0s`}),setTimeout(function(){e.css("opacity","1")},0))},fadeOut:function(e){e.length&&(e.css({opacity:"0",transition:`opacity ${o.config.speed}ms ease-in 0s`}),setTimeout(function(){e.css("display","none")},o.config.speed))},collapseAllCategories:function(){n.$categories.find(".wpforms-builder-help-category").removeClass("opened"),n.$categories.find(".wpforms-builder-help-docs").slideUp()}},a={openHelp:function(e){e.preventDefault();var e=n.$categories.find(".wpforms-builder-help-category").first(),r=p.getBuilderContextTerm();""!==r||e.hasClass("opened")?o.collapseAllCategories():e.find("header").first().trigger("click"),n.$search.find("input").val(r).trigger("keyup"),o.fadeIn(n.$help),setTimeout(function(){o.fadeIn(n.$result),o.fadeIn(n.$categories),o.fadeIn(n.$footer)},o.config.speed)},closeHelp:function(e){e.preventDefault(),o.fadeOut(n.$result),o.fadeOut(n.$categories),o.fadeOut(n.$footer),o.fadeOut(n.$help)},toggleCategory:function(e){var r=l(this).parent(),t=r.find(".wpforms-builder-help-docs");t.is(":visible")?r.removeClass("opened"):r.addClass("opened"),t.stop().slideToggle(o.config.speed)},viewAllCategoryDocs:function(e){var r=l(this);r.prev("div").stop().slideToggle(o.config.speed,function(){r.closest(".wpforms-builder-help-category").addClass("viewall")}),o.fadeOut(r),r.slideUp()},inputSearch:function(e){var r=l(this).val(),t=wp.template("wpforms-builder-help-docs"),o=p.getRecommendedDocs(r),i=a.removeDuplicates(o,p.getFilteredDocs(r)),s="";n.$search.toggleClass("wpforms-empty",!r),wpf.empty(o)||(s+=t({docs:o})),wpf.empty(i)||(s+=t({docs:i})),n.$noResult.toggle(""===s&&""!==r),n.$result.html(s),n.$help[0].scrollTop=0},removeDuplicates:function(e,r){if(wpf.empty(e)||wpf.empty(r))return r;for(var t=[],o=0;e.length,o++;)for(var i=0;r.length,i++;)r[i].url!==e[o].url&&t.push(r[i]);return t},clearSearch:function(e){n.$search.find("input").val("").trigger("keyup")}};return p}((document,window,jQuery)),WPForms.Admin.Builder.Help.init();

View File

@@ -0,0 +1,236 @@
/* global wpforms_builder, wpf */
/**
* Form Builder Panel Loader module.
*
* @since 1.8.6
*/
var WPForms = window.WPForms || {}; // eslint-disable-line no-var
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.PanelLoader = WPForms.Admin.Builder.PanelLoader || ( function( document, window, $ ) {
/**
* Elements holder.
*
* @since 1.8.6
*
* @type {Object}
*/
const el = {};
/**
* Runtime variables.
*
* @since 1.8.6
*
* @type {Object}
*/
const vars = [];
/**
* Public functions and properties.
*
* @since 1.8.6
*
* @type {Object}
*/
const app = {
/**
* Start the engine.
*
* @since 1.8.6
*/
init() {
$( app.ready );
},
/**
* DOM is fully loaded.
*
* @since 1.8.6
*/
ready() {
app.setup();
app.events();
el.$builder.trigger( 'wpformsBuilderLoaderReady' );
},
/**
* Setup. Prepare some variables.
*
* @since 1.8.6
*/
setup() {
// Cache DOM elements.
el.$builder = $( '#wpforms-builder' );
el.$form = $( '#wpforms-builder-form' );
el.$panels = el.$builder.find( '.wpforms-panels' );
// Init vars.
vars.currentPanel = wpf.getQueryString( 'view' );
},
/**
* Bind events.
*
* @since 1.8.6
*/
events() {
// Panel switching.
el.$builder.on( 'wpformsPanelSwitch', function( e, panel ) {
// Skip if the panel is still loading.
if ( el.$builder.find( `.wpforms-panel-${ panel }-button .wpforms-loading-spinner` ).length ) {
e.preventDefault();
return;
}
// Open the panel if it is already loaded.
if ( el.$panels.find( '#wpforms-panel-' + panel ).length ) {
return;
}
// Load panel.
e.preventDefault();
app.loadPanel( panel );
} );
},
/**
* Load panel.
*
* @since 1.8.6
*
* @param {string} panel Panel name.
*/
loadPanel( panel ) {
app.showSpinner( panel );
// Load panel.
$.post( wpforms_builder.ajax_url, {
nonce: wpforms_builder.nonce,
action: 'wpforms_builder_load_panel',
panel,
form_id: wpf.getQueryString( 'form_id' ), // eslint-disable-line camelcase
} )
.done( function( response ) {
if ( ! response.success || ! response.data?.length ) {
// Show an error message.
app.displayErrorModal( `<p>${ wpforms_builder.error_load_templates }</p><p>${ wpforms_builder.error_contact_support }</p>` );
return;
}
// Append panel to the DOM.
app.embedPanel( panel, response.data );
// Finalize switching to the panel.
app.switchPanel( panel );
// Trigger panel loaded event.
el.$builder.trigger( 'wpformsBuilderPanelLoaded', [ panel ] );
} )
.fail( function() {
// Show an error message.
app.displayErrorModal( `<p>${ wpforms_builder.something_went_wrong }.</p><p>${ wpforms_builder.error_contact_support }</p>` );
} )
.always( function() {
// Hide loading spinner.
app.hideSpinner( panel );
} );
},
/**
* Show spinner.
*
* @since 1.8.6
*
* @param {string} panel Panel name.
*/
showSpinner( panel ) {
const $button = $( `.wpforms-panel-${ panel }-button` );
$button.find( `i.fa` ).addClass( 'wpforms-hidden' );
$button.prepend( '<i class="wpforms-loading-spinner wpforms-loading-white"></i>' );
},
/**
* Hide spinner.
*
* @since 1.8.6
*
* @param {string} panel Panel name.
*/
hideSpinner( panel ) {
const $button = $( `.wpforms-panel-${ panel }-button` );
$button.find( `i.fa` ).removeClass( 'wpforms-hidden' );
$button.find( `i.wpforms-loading-spinner` ).remove();
},
/**
* Embed panel to DOM.
*
* @since 1.8.6
*
* @param {string} panel Panel slug.
* @param {string} panelHtml Panel HTML.
*/
embedPanel( panel, panelHtml ) {
// Append panel to the DOM.
el.$panels.append( panelHtml );
},
/**
* Finalize switching to the panel.
*
* @since 1.8.6
*
* @param {string} panel Panel slug.
*/
switchPanel( panel ) {
$( '#wpforms-panels-toggle' ).find( 'button' ).removeClass( 'active' );
$( '.wpforms-panel' ).removeClass( 'active' );
$( `.wpforms-panel-${ panel }-button` ).addClass( 'active' );
$( `#wpforms-panel-${ panel }` ).addClass( 'active' );
history.replaceState( {}, null, wpf.updateQueryString( 'view', panel ) );
el.$builder.trigger( 'wpformsPanelSwitched', [ panel ] );
},
/**
* Display modal window with an error message.
*
* @since 1.8.6
*
* @param {string} content Modal content.
*/
displayErrorModal( content ) {
$.alert( {
title : wpforms_builder.uh_oh,
content,
icon : 'fa fa-exclamation-circle',
type : 'red',
buttons: {
cancel: {
text : wpforms_builder.close,
btnClass: 'btn-confirm',
keys : [ 'enter' ],
},
},
} );
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.PanelLoader.init();

View File

@@ -0,0 +1 @@
var WPForms=window.WPForms||{};WPForms.Admin=WPForms.Admin||{},WPForms.Admin.Builder=WPForms.Admin.Builder||{},WPForms.Admin.Builder.PanelLoader=WPForms.Admin.Builder.PanelLoader||function(n){const o={},e=[],i={init(){n(i.ready)},ready(){i.setup(),i.events(),o.$builder.trigger("wpformsBuilderLoaderReady")},setup(){o.$builder=n("#wpforms-builder"),o.$form=n("#wpforms-builder-form"),o.$panels=o.$builder.find(".wpforms-panels"),e.currentPanel=wpf.getQueryString("view")},events(){o.$builder.on("wpformsPanelSwitch",function(e,r){o.$builder.find(`.wpforms-panel-${r}-button .wpforms-loading-spinner`).length?e.preventDefault():o.$panels.find("#wpforms-panel-"+r).length||(e.preventDefault(),i.loadPanel(r))})},loadPanel(r){i.showSpinner(r),n.post(wpforms_builder.ajax_url,{nonce:wpforms_builder.nonce,action:"wpforms_builder_load_panel",panel:r,form_id:wpf.getQueryString("form_id")}).done(function(e){e.success&&e.data?.length?(i.embedPanel(r,e.data),i.switchPanel(r),o.$builder.trigger("wpformsBuilderPanelLoaded",[r])):i.displayErrorModal(`<p>${wpforms_builder.error_load_templates}</p><p>${wpforms_builder.error_contact_support}</p>`)}).fail(function(){i.displayErrorModal(`<p>${wpforms_builder.something_went_wrong}.</p><p>${wpforms_builder.error_contact_support}</p>`)}).always(function(){i.hideSpinner(r)})},showSpinner(e){e=n(`.wpforms-panel-${e}-button`);e.find("i.fa").addClass("wpforms-hidden"),e.prepend('<i class="wpforms-loading-spinner wpforms-loading-white"></i>')},hideSpinner(e){e=n(`.wpforms-panel-${e}-button`);e.find("i.fa").removeClass("wpforms-hidden"),e.find("i.wpforms-loading-spinner").remove()},embedPanel(e,r){o.$panels.append(r)},switchPanel(e){n("#wpforms-panels-toggle").find("button").removeClass("active"),n(".wpforms-panel").removeClass("active"),n(`.wpforms-panel-${e}-button`).addClass("active"),n("#wpforms-panel-"+e).addClass("active"),history.replaceState({},null,wpf.updateQueryString("view",e)),o.$builder.trigger("wpformsPanelSwitched",[e])},displayErrorModal(e){n.alert({title:wpforms_builder.uh_oh,content:e,icon:"fa fa-exclamation-circle",type:"red",buttons:{cancel:{text:wpforms_builder.close,btnClass:"btn-confirm",keys:["enter"]}}})}};return i}((document,window,jQuery)),WPForms.Admin.Builder.PanelLoader.init();

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,207 @@
/**
* WPForms Builder Search module.
*
* @since 1.8.3
*/
'use strict';
var WPForms = window.WPForms || {};
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.Search = WPForms.Admin.Builder.Search || ( function( document, window, $ ) {
/**
* Elements holder.
*
* @since 1.8.3
*
* @type {object}
*/
const el = {};
/**
* Public functions and properties.
*
* @since 1.8.3
*
* @type {object}
*/
const app = {
/**
* Start the engine. DOM is not ready yet, use only to init something.
*
* @since 1.8.3
*/
init: function() {
$( app.ready );
},
/**
* DOM is fully loaded.
*
* @since 1.8.3
*/
ready: function() {
app.setup();
app.events();
app.scrollSidebar();
},
/**
* Scroll the sidebar to the height of the search.
*
* @since 1.8.3
*/
scrollSidebar: function() {
el.$sidebar.scrollTop( el.$searchWrapper.height() + 20 );
},
/**
* Setup. Prepare some variables.
*
* @since 1.8.3
*/
setup: function() {
// Cache DOM elements
el.$document = $( document );
el.$builder = $( '#wpforms-builder' );
el.$searchInput = $( '#wpforms-search-fields-input' );
el.$searchInputCloseBtn = $( '.wpforms-search-fields-input-close' );
el.$searchWrapper = $( '.wpforms-search-fields-wrapper' );
el.$noResults = $( '.wpforms-search-fields-no-results' );
el.$listWrapper = $( '.wpforms-search-fields-list' );
el.$list = $( '.wpforms-search-fields-list .wpforms-add-fields-buttons' );
el.$groups = $( '.wpforms-tab-content > .wpforms-add-fields-group' );
el.$sidebar = $( '#wpforms-panel-fields .wpforms-add-fields' );
},
/**
* Bind events.
*
* @since 1.8.3
*/
events: function() {
el.$searchInput.on( 'keyup', app.searchAction );
el.$searchInputCloseBtn.on( 'click', app.clearSearch );
el.$document.on( 'wpformsFieldAdd', app.clearSearch );
el.$document.on( 'wpformsFieldDelete', app.refreshSearchResults );
},
/**
* Search action.
*
* @since 1.8.3
*/
searchAction: function() {
const $fields = el.$builder.find( '.wpforms-tab-content > .wpforms-add-fields-group .wpforms-add-fields-button' );
const searchValue = el.$searchInput.val().toLowerCase();
el.$list.empty();
if ( searchValue ) {
el.$groups.hide();
el.$listWrapper.show();
el.$searchInputCloseBtn.addClass( 'active' );
$fields.each( function() {
const $item = $( this );
const titleText = $item.text().toLowerCase();
const keywords = $item.data( 'field-keywords' ) ? $item.data( 'field-keywords' ).toLowerCase() : '';
if ( titleText.indexOf( searchValue ) >= 0 || ( keywords && keywords.indexOf( searchValue ) >= 0 ) ) {
const $clone = $item.clone();
$clone.attr( 'data-target', $clone.attr( 'id' ) );
$clone.removeAttr( 'id' );
$clone.addClass( 'wpforms-add-fields-button-clone' );
el.$list.append( $clone );
}
} );
const $matchingItems = el.$list.find( '.wpforms-add-fields-button' );
const hasMatchingItems = $matchingItems.length > 0;
if ( hasMatchingItems ) {
el.$noResults.hide();
} else {
el.$noResults.show();
el.$listWrapper.hide();
}
} else {
el.$groups.show();
el.$listWrapper.hide();
el.$noResults.hide();
el.$searchInputCloseBtn.removeClass( 'active' );
}
WPForms.Admin.Builder.DragFields.setup();
WPForms.Admin.Builder.DragFields.initSortableFields();
app.cloneClickAction();
},
/**
* Clear search.
*
* @since 1.8.3
*/
clearSearch: function() {
if ( ! el.$searchInput.val() ) {
return;
}
el.$list.empty();
el.$listWrapper.hide();
el.$groups.show();
el.$noResults.hide();
el.$searchInput.val( '' ).focus();
el.$searchInputCloseBtn.removeClass( 'active' );
},
/**
* Refresh search results.
*
* @since 1.8.3
*/
refreshSearchResults: function() {
// We need to wait for the original field to be unlocked.
setTimeout( app.searchAction, 0 );
},
/**
* Clone click action.
*
* @since 1.8.3
*/
cloneClickAction() {
$( '.wpforms-add-fields-button-clone' ).on( 'click', function( e ) {
e.preventDefault();
e.stopPropagation();
const target = $( this ).attr( 'data-target' );
$( '#' + target ).trigger( 'click' );
} );
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.Search.init();

View File

@@ -0,0 +1 @@
"use strict";var WPForms=window.WPForms||{};WPForms.Admin=WPForms.Admin||{},WPForms.Admin.Builder=WPForms.Admin.Builder||{},WPForms.Admin.Builder.Search=WPForms.Admin.Builder.Search||function(e,o){const i={},s={init:function(){o(s.ready)},ready:function(){s.setup(),s.events(),s.scrollSidebar()},scrollSidebar:function(){i.$sidebar.scrollTop(i.$searchWrapper.height()+20)},setup:function(){i.$document=o(e),i.$builder=o("#wpforms-builder"),i.$searchInput=o("#wpforms-search-fields-input"),i.$searchInputCloseBtn=o(".wpforms-search-fields-input-close"),i.$searchWrapper=o(".wpforms-search-fields-wrapper"),i.$noResults=o(".wpforms-search-fields-no-results"),i.$listWrapper=o(".wpforms-search-fields-list"),i.$list=o(".wpforms-search-fields-list .wpforms-add-fields-buttons"),i.$groups=o(".wpforms-tab-content > .wpforms-add-fields-group"),i.$sidebar=o("#wpforms-panel-fields .wpforms-add-fields")},events:function(){i.$searchInput.on("keyup",s.searchAction),i.$searchInputCloseBtn.on("click",s.clearSearch),i.$document.on("wpformsFieldAdd",s.clearSearch),i.$document.on("wpformsFieldDelete",s.refreshSearchResults)},searchAction:function(){var e=i.$builder.find(".wpforms-tab-content > .wpforms-add-fields-group .wpforms-add-fields-button");const t=i.$searchInput.val().toLowerCase();i.$list.empty(),t?(i.$groups.hide(),i.$listWrapper.show(),i.$searchInputCloseBtn.addClass("active"),e.each(function(){var e=o(this),s=e.text().toLowerCase(),r=e.data("field-keywords")?e.data("field-keywords").toLowerCase():"";(0<=s.indexOf(t)||r&&0<=r.indexOf(t))&&((s=e.clone()).attr("data-target",s.attr("id")),s.removeAttr("id"),s.addClass("wpforms-add-fields-button-clone"),i.$list.append(s))}),(0<i.$list.find(".wpforms-add-fields-button").length?i.$noResults:(i.$noResults.show(),i.$listWrapper)).hide()):(i.$groups.show(),i.$listWrapper.hide(),i.$noResults.hide(),i.$searchInputCloseBtn.removeClass("active")),WPForms.Admin.Builder.DragFields.setup(),WPForms.Admin.Builder.DragFields.initSortableFields(),s.cloneClickAction()},clearSearch:function(){i.$searchInput.val()&&(i.$list.empty(),i.$listWrapper.hide(),i.$groups.show(),i.$noResults.hide(),i.$searchInput.val("").focus(),i.$searchInputCloseBtn.removeClass("active"))},refreshSearchResults:function(){setTimeout(s.searchAction,0)},cloneClickAction(){o(".wpforms-add-fields-button-clone").on("click",function(e){e.preventDefault(),e.stopPropagation();e=o(this).attr("data-target");o("#"+e).trigger("click")})}};return s}(document,(window,jQuery)),WPForms.Admin.Builder.Search.init();

View File

@@ -0,0 +1,330 @@
/* global wpforms_builder_settings, Choices, wpf */
// noinspection ES6ConvertVarToLetConst
/**
* Form Builder Settings Panel module.
*
* @since 1.7.5
*/
// eslint-disable-next-line no-var
var WPForms = window.WPForms || {};
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.Settings = WPForms.Admin.Builder.Settings || ( function( document, window, $ ) {
/**
* Elements holder.
*
* @since 1.7.5
*
* @type {Object}
*/
let el = {};
/**
* Runtime variables.
*
* @since 1.7.5
*
* @type {Object}
*/
const vars = {};
// noinspection JSUnusedLocalSymbols,ES6ConvertVarToLetConst
/**
* Public functions and properties.
*
* @since 1.7.5
*
* @type {Object}
*/
// eslint-disable-next-line no-var
var app = {
/**
* Start the engine.
*
* @since 1.7.5
*/
init() {
$( app.ready );
},
/**
* DOM is fully loaded.
*
* @since 1.7.5
*/
ready() {
app.setup();
app.initTags();
app.events();
},
/**
* Setup. Prepare some variables.
*
* @since 1.7.5
*/
setup() {
// Cache DOM elements.
el = {
$builder: $( '#wpforms-builder' ),
$panel: $( '#wpforms-panel-settings' ),
$selectTags: $( '#wpforms-panel-field-settings-form_tags' ),
};
},
/**
* Bind events.
*
* @since 1.7.5
*/
events() {
el.$panel
.on( 'keydown', '#wpforms-panel-field-settings-form_tags-wrap input', app.addCustomTagInput )
.on( 'removeItem', '#wpforms-panel-field-settings-form_tags-wrap select', app.editTagsRemoveItem )
.on( 'change', '#wpforms-panel-field-settings-antispam_v3', app.enableAntispamV3 )
.on( 'change', '#wpforms-panel-field-settings-disable_entries', app.disableEntries )
.on( 'change', '#wpforms-panel-field-settings-store_spam_entries', app.storeSpamEntries );
el.$selectTags
.on( 'change', app.changeTags );
},
/**
* Enable Anti spam v3 toggle change event.
*
* @since 1.9.0
*/
enableAntispamV3() {
// Hide and disable old anti-spam.
$( '#wpforms-panel-field-settings-antispam' )
.prop( 'checked', false )
.closest( '.wpforms-panel-field' )
.toggleClass( 'wpforms-hidden' );
},
/**
* Disable Entries toggle change event.
*
* @since 1.9.2
*/
disableEntries() {
app.toggleFilteringMessages( ! $( this ).prop( 'checked' ) && $( '#wpforms-panel-field-settings-store_spam_entries' ).prop( 'checked' ) );
},
/**
* Store Spam Entries toggle change event.
*
* @since 1.9.2
*/
storeSpamEntries() {
app.toggleFilteringMessages( $( this ).prop( 'checked' ) );
},
/**
* Toggle Filtering Messages.
*
* @since 1.9.2
*
* @param {boolean} $hide Whether to hide or show messages.
*/
toggleFilteringMessages( $hide ) {
if ( ! $( '#wpforms-panel-field-anti_spam-filtering_store_spam' ).is( ':checked' ) ) {
return;
}
// Toggle Country Filter Message.
$( '#wpforms-panel-field-anti_spam-country_filter-message-wrap' ).toggleClass( 'wpforms-hidden', $hide );
// Toggle Keyywords Filter Message.
$( '#wpforms-panel-field-anti_spam-keyword_filter-message-wrap' ).toggleClass( 'wpforms-hidden', $hide );
},
/**
* Init Choices.js on the Tags select an input element.
*
* @param {Object} $el Element.
* @since 1.7.5
*/
initTags( $el = null ) {
$el = $el?.length ? $el : el.$selectTags;
// Skip in certain cases.
if (
! $el.length ||
typeof window.Choices !== 'function'
) {
return;
}
// Init Choices.js object instance.
vars.tagsChoicesObj = new Choices( $el[ 0 ], wpforms_builder_settings.choicesjs_config );
// Backup current value.
const currentValue = vars.tagsChoicesObj.getValue( true );
// Update all tags choices.
vars.tagsChoicesObj
.clearStore()
.setChoices(
wpforms_builder_settings.all_tags_choices,
'value',
'label',
true
)
.setChoiceByValue( currentValue );
$el.data( 'choicesjs', vars.tagsChoicesObj );
app.initTagsHiddenInput();
},
/**
* Init Tags hidden input element.
*
* @since 1.7.5
*/
initTagsHiddenInput() {
// Create additional hidden input.
el.$selectTagsHiddenInput = $( '<input type="hidden" name="settings[form_tags_json]">' );
el.$selectTags
.closest( '.wpforms-panel-field' )
.append( el.$selectTagsHiddenInput );
// Update hidden input value.
app.changeTags( null );
// Update form state when hidden input initialized.
// This will prevent a please-save-prompt to appear when switching from revisions without doing any changes anywhere.
if ( wpf.initialSave === true ) {
wpf.savedState = wpf.getFormState( '#wpforms-builder-form' );
}
},
/**
* Add custom item to Tags dropdown on input.
*
* @since 1.7.5
*
* @param {Object} event Event object.
*/
addCustomTagInput( event ) {
if ( [ 'Enter', ',' ].indexOf( event.key ) < 0 ) {
return;
}
event.preventDefault();
event.stopPropagation();
if ( ! vars.tagsChoicesObj || event.target.value.length === 0 ) {
return;
}
const tagLabel = _.escape( event.target.value ).trim(),
labels = _.map( vars.tagsChoicesObj.getValue(), 'label' ).map( function( label ) {
return label.toLowerCase().trim();
} );
if ( tagLabel === '' || labels.indexOf( tagLabel.toLowerCase() ) >= 0 ) {
vars.tagsChoicesObj.clearInput();
return;
}
app.addCustomTagInputCreate( tagLabel );
app.changeTags( event );
},
/**
* Remove tag from Tags field event handler.
*
* @since 1.7.5
*
* @param {Object} event Event object.
*/
editTagsRemoveItem( event ) {
const allValues = _.map( wpforms_builder_settings.all_tags_choices, 'value' );
if ( allValues.indexOf( event.detail.value ) >= 0 ) {
return;
}
// We should remove new tag from the list of choices.
const choicesObj = $( event.target ).data( 'choicesjs' ),
currentValue = choicesObj.getValue( true ),
choices = _.filter( choicesObj._currentState.choices, function( item ) {
return item.value !== event.detail.value;
} );
choicesObj
.clearStore()
.setChoices( choices, 'value', 'label', true )
.setChoiceByValue( currentValue );
},
/**
* Add custom item to Tags dropdown on input (second part).
*
* @since 1.7.5
*
* @param {Object} tagLabel Event object.
*/
addCustomTagInputCreate( tagLabel ) {
const tag = _.find( wpforms_builder_settings.all_tags_choices, { label: tagLabel } );
if ( tag && tag.value ) {
vars.tagsChoicesObj.setChoiceByValue( tag.value );
} else {
vars.tagsChoicesObj.setChoices(
[
{
value: tagLabel,
label: tagLabel,
selected: true,
},
],
'value',
'label',
false
);
}
vars.tagsChoicesObj.clearInput();
},
/**
* Change Tags field event handler.
*
* @since 1.7.5
*
* @param {Object} event Event object.
*/
// eslint-disable-next-line no-unused-vars
changeTags( event ) {
const tagsValue = vars.tagsChoicesObj.getValue(),
tags = [];
for ( let i = 0; i < tagsValue.length; i++ ) {
tags.push( {
value: tagsValue[ i ].value,
label: tagsValue[ i ].label,
} );
}
// Update Tags field hidden input value.
el.$selectTagsHiddenInput.val(
JSON.stringify( tags )
);
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.Settings.init();

View File

@@ -0,0 +1 @@
var WPForms=window.WPForms||{};WPForms.Admin=WPForms.Admin||{},WPForms.Admin.Builder=WPForms.Admin.Builder||{},WPForms.Admin.Builder.Settings=WPForms.Admin.Builder.Settings||function(t,i){let a={};const n={};var l={init(){i(l.ready)},ready(){l.setup(),l.initTags(),l.events()},setup(){a={$builder:i("#wpforms-builder"),$panel:i("#wpforms-panel-settings"),$selectTags:i("#wpforms-panel-field-settings-form_tags")}},events(){a.$panel.on("keydown","#wpforms-panel-field-settings-form_tags-wrap input",l.addCustomTagInput).on("removeItem","#wpforms-panel-field-settings-form_tags-wrap select",l.editTagsRemoveItem).on("change","#wpforms-panel-field-settings-antispam_v3",l.enableAntispamV3).on("change","#wpforms-panel-field-settings-disable_entries",l.disableEntries).on("change","#wpforms-panel-field-settings-store_spam_entries",l.storeSpamEntries),a.$selectTags.on("change",l.changeTags)},enableAntispamV3(){i("#wpforms-panel-field-settings-antispam").prop("checked",!1).closest(".wpforms-panel-field").toggleClass("wpforms-hidden")},disableEntries(){l.toggleFilteringMessages(!i(this).prop("checked")&&i("#wpforms-panel-field-settings-store_spam_entries").prop("checked"))},storeSpamEntries(){l.toggleFilteringMessages(i(this).prop("checked"))},toggleFilteringMessages(e){i("#wpforms-panel-field-anti_spam-filtering_store_spam").is(":checked")&&(i("#wpforms-panel-field-anti_spam-country_filter-message-wrap").toggleClass("wpforms-hidden",e),i("#wpforms-panel-field-anti_spam-keyword_filter-message-wrap").toggleClass("wpforms-hidden",e))},initTags(e=null){var s;(e=e?.length?e:a.$selectTags).length&&"function"==typeof t.Choices&&(n.tagsChoicesObj=new Choices(e[0],wpforms_builder_settings.choicesjs_config),s=n.tagsChoicesObj.getValue(!0),n.tagsChoicesObj.clearStore().setChoices(wpforms_builder_settings.all_tags_choices,"value","label",!0).setChoiceByValue(s),e.data("choicesjs",n.tagsChoicesObj),l.initTagsHiddenInput())},initTagsHiddenInput(){a.$selectTagsHiddenInput=i('<input type="hidden" name="settings[form_tags_json]">'),a.$selectTags.closest(".wpforms-panel-field").append(a.$selectTagsHiddenInput),l.changeTags(null),!0===wpf.initialSave&&(wpf.savedState=wpf.getFormState("#wpforms-builder-form"))},addCustomTagInput(e){var s,t;["Enter",","].indexOf(e.key)<0||(e.preventDefault(),e.stopPropagation(),n.tagsChoicesObj&&0!==e.target.value.length&&(s=_.escape(e.target.value).trim(),t=_.map(n.tagsChoicesObj.getValue(),"label").map(function(e){return e.toLowerCase().trim()}),""===s||0<=t.indexOf(s.toLowerCase())?n.tagsChoicesObj.clearInput():(l.addCustomTagInputCreate(s),l.changeTags(e))))},editTagsRemoveItem(s){var e,t,a;0<=_.map(wpforms_builder_settings.all_tags_choices,"value").indexOf(s.detail.value)||(t=(e=i(s.target).data("choicesjs")).getValue(!0),a=_.filter(e._currentState.choices,function(e){return e.value!==s.detail.value}),e.clearStore().setChoices(a,"value","label",!0).setChoiceByValue(t))},addCustomTagInputCreate(e){var s=_.find(wpforms_builder_settings.all_tags_choices,{label:e});s&&s.value?n.tagsChoicesObj.setChoiceByValue(s.value):n.tagsChoicesObj.setChoices([{value:e,label:e,selected:!0}],"value","label",!1),n.tagsChoicesObj.clearInput()},changeTags(e){var s=n.tagsChoicesObj.getValue(),t=[];for(let e=0;e<s.length;e++)t.push({value:s[e].value,label:s[e].label});a.$selectTagsHiddenInput.val(JSON.stringify(t))}};return l}((document,window),jQuery),WPForms.Admin.Builder.Settings.init();

View File

@@ -0,0 +1,749 @@
/* global wpforms_builder, wpf, WPFormsBuilder, WPFormsFormTemplates */
/* eslint-disable no-console */
/**
* @param wpforms_builder.blank_form
* @param wpforms_builder.error_select_template
* @param wpforms_builder.form_meta
* @param wpforms_builder.template_confirm
* @param wpforms_builder.use_default_template
*/
// noinspection ES6ConvertVarToLetConst
/**
* Form Builder Setup Panel module.
*
* @since 1.6.8
*/
var WPForms = window.WPForms || {}; // eslint-disable-line no-var
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.Setup = WPForms.Admin.Builder.Setup || ( function( document, window, $ ) {
/**
* Elements holder.
*
* @since 1.6.8
*
* @type {Object}
*/
const el = {};
/**
* Runtime variables.
*
* @since 1.6.8
*
* @type {Object}
*/
const vars = {};
/**
* Active template name.
*
* @since 1.7.6
*/
const activeTemplateName = $( '.wpforms-template.selected .wpforms-template-name' ).text().trim();
/**
* Public functions and properties.
*
* @since 1.6.8
*
* @type {Object}
*/
const app = {
/**
* Start the engine.
*
* @since 1.6.8
*/
init() {
$( app.ready );
// Page load.
$( window ).on( 'load', function() {
// In the case of jQuery 3.+, we need to wait for a ready event first.
if ( typeof $.ready.then === 'function' ) {
$.ready.then( app.load );
} else {
app.load();
}
} );
},
/**
* DOM is fully loaded.
*
* @since 1.6.8
*/
ready() {
app.setup();
app.setPanelsToggleState();
app.setupTitleFocus();
app.setTriggerBlankLink();
app.events();
// Trigger `wpformsBuilderPanelLoaded` event only when the panel is available in DOM.
if ( el.$panel.length ) {
el.$builder.trigger( 'wpformsBuilderPanelLoaded', [ 'setup' ] );
}
el.$builder.trigger( 'wpformsBuilderSetupReady' );
},
/**
* Page load.
*
* @since 1.6.8
*/
load() {
app.applyTemplateOnRequest();
},
/**
* Setup. Prepare some variables.
*
* @since 1.6.8
*/
setup() {
// Cache DOM elements.
el.$builder = $( '#wpforms-builder' );
el.$form = $( '#wpforms-builder-form' );
el.$formName = $( '#wpforms-setup-name' );
el.$panel = $( '#wpforms-panel-setup' );
el.$categories = $( '#wpforms-panel-setup .wpforms-setup-templates-categories' );
el.$subcategories = $( '#wpforms-panel-setup .wpforms-setup-templates-subcategories' );
// Other values.
vars.spinner = '<i class="wpforms-loading-spinner wpforms-loading-white wpforms-loading-inline"></i>';
vars.formID = el.$form.data( 'id' );
},
/**
* Bind events.
*
* @since 1.6.8
*/
events() {
el.$builder.on( 'wpformsBuilderPanelLoaded', app.panelLoaded );
// Focus on the form title field when displaying a setup panel.
el.$builder
.on( 'wpformsPanelSwitched', app.setupTitleFocus );
// Sync Setup title and settings title.
el.$builder
.on( 'input', '#wpforms-panel-field-settings-form_title', app.syncTitle )
.on( 'input', '#wpforms-setup-name', app.syncTitle );
},
/**
* Bind panel events.
*
* @since 1.8.6
*/
panelEvents() {
el.$panel
.on( 'keyup', '#wpforms-setup-template-search', _.debounce( WPFormsFormTemplates.searchTemplate, 200 ) )
.on( 'click', '.wpforms-setup-templates-categories li div', WPFormsFormTemplates.selectCategory )
.on( 'click', '.wpforms-setup-templates-categories li .chevron', WPFormsFormTemplates.toggleSubcategoriesList )
.on( 'click', '.wpforms-setup-templates-subcategories li', WPFormsFormTemplates.selectSubCategory )
.on( 'click', '.wpforms-template-select', app.selectTemplate )
.on( 'click', '.wpforms-trigger-blank', app.selectBlankTemplate );
el.$builder
.on( 'wpformsBuilderReady wpformsBuilderPanelLoaded', app.filterTemplatesBySelectedCategory );
},
/**
* Panel loaded event.
*
* @since 1.8.6
*
* @param {Object} e Event object.
* @param {string} panel Panel name.
*/
panelLoaded( e, panel ) {
if ( panel !== 'setup' ) {
return;
}
WPFormsFormTemplates.setup();
app.setup();
app.setSelectedTemplate();
app.setSelectedCategories();
app.panelEvents();
},
/**
* Set panels toggle buttons state.
*
* @since 1.6.8
*/
setPanelsToggleState() {
el.$builder
.find( '#wpforms-panels-toggle button:not(.active)' )
.toggleClass( 'wpforms-disabled', vars.formID === '' );
},
/**
* Set attributes of "blank template" link.
*
* @since 1.6.8
*/
setTriggerBlankLink() {
el.$builder
.find( '.wpforms-trigger-blank' )
.attr( {
'data-template-name-raw': 'Blank Form',
'data-template': 'blank',
} );
},
/**
* Force focus on the form title field when switched to the Setup panel.
*
* @since 1.6.8
*
* @param {Object|null} e Event object.
* @param {string|null} view Current view.
*/
setupTitleFocus( e = null, view = null ) { // eslint-disable-line no-unused-vars
view = view || wpf.getQueryString( 'view' );
if ( view !== 'setup' ) {
return;
}
// Clone form title to the Setup page.
$( '#wpforms-setup-name' ).val( $( '#wpforms-panel-field-settings-form_title' ).val() );
el.$formName.trigger( 'focus' );
},
/**
* Mark the current form template as selected.
*
* @since 1.8.6
*/
setSelectedTemplate() {
if ( ! el.$panel.length || ! wpforms_builder.form_meta?.template ) {
return;
}
const $template = el.$builder
.find( `.wpforms-template-select[data-template="${ wpforms_builder.form_meta.template }"]` )
.closest( '.wpforms-template' );
if ( ! $template.length ) {
return;
}
$template
.addClass( 'selected' )
.addClass( 'badge' );
// Remove existing badge.
$template.find( '.wpforms-badge' ).remove();
// Remove edit and delete action buttons from current user template.
if ( $template.hasClass( 'wpforms-user-template' ) ) {
$template.find( '.wpforms-template-edit, .wpforms-template-remove' ).remove();
}
},
/**
* Set category and/or subcategory active if its template was selected.
*
* @since 1.8.9
*/
setSelectedCategories() {
if ( ! el.$panel.length || ! wpforms_builder.form_meta?.category ) {
return;
}
const $category = el.$categories.find( `li[data-category="${ wpforms_builder.form_meta.category }"]` );
if ( ! $category.length ) {
return;
}
el.$categories.find( 'li' ).removeClass( 'active opened' );
$category.addClass( 'active opened' );
const $subcategory = el.$subcategories.find( `li[data-subcategory="${ wpforms_builder.form_meta.subcategory }"]` );
if ( ! $subcategory.length ) {
return;
}
el.$subcategories.find( 'li' ).removeClass( 'active' );
$subcategory.addClass( 'active' );
},
/**
* Filter templates by selected category and subcategory.
*
* @since 1.8.9
*/
filterTemplatesBySelectedCategory() {
const $subCategory = el.$subcategories.find( 'li.active' );
// If subcategory is available, trigger its click it will update and category also.
if ( $subCategory.length ) {
$subCategory.trigger( 'click' );
}
const $category = el.$categories.find( '> li.active' );
// In another case, click on the category.
if (
! $subCategory.length &&
$category.length &&
$category.data( 'category' ) !== 'all'
) {
$category.find( 'div' ).trigger( 'click' );
}
},
/**
* Keep Setup title and settings title instances the same.
*
* @since 1.6.8
*
* @param {Object} e Event object.
*/
syncTitle( e ) {
if ( e.target.id === 'wpforms-setup-name' ) {
$( '#wpforms-panel-field-settings-form_title' ).val( e.target.value );
} else {
$( '#wpforms-setup-name' ).val( e.target.value );
}
},
/**
* Search template.
*
* @since 1.6.8
* @since 1.7.7 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.searchTemplate` instead.
*
* @param {Object} e Event object.
*/
searchTemplate( e ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.searchTemplate( e )" has been deprecated, please use the new "WPFormsFormTemplates.searchTemplate( e )" function instead!' );
WPFormsFormTemplates.searchTemplate( e );
},
/**
* Select category.
*
* @since 1.6.8
* @since 1.7.7 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.selectCategory` instead.
*
* @param {Object} e Event object.
*/
selectCategory( e ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.selectCategory( e )" has been deprecated, please use the new "WPFormsFormTemplates.selectCategory( e )" function instead!' );
WPFormsFormTemplates.selectCategory( e );
},
/**
* Select template.
*
* @since 1.6.8
*
* @param {Object} event Event object.
*/
selectTemplate( event ) {
event.preventDefault();
const $button = $( this );
// Don't do anything for templates that trigger education modal OR addons-modal.
if ( $button.hasClass( 'education-modal' ) ) {
return;
}
const template = $button.data( 'template' );
// User templates are applied differently for new forms.
if ( ! vars.formID && template.match( /wpforms-user-template-(\d+)/ ) && $button.data( 'create-url' ) ) {
window.location.href = $button.data( 'create-url' );
return;
}
el.$panel.find( '.wpforms-template' ).removeClass( 'active' );
$button.closest( '.wpforms-template' ).addClass( 'active' );
// Save the original label.
$button.data( 'labelOriginal', $button.html() );
// Display loading indicator.
$button.html( vars.spinner + wpforms_builder.loading );
const formName = app.getFormName( $button );
app.applyTemplate( formName, template, $button );
},
/**
* Get form name.
*
* @since 1.7.6
*
* @param {jQuery} $button Pressed template button.
*
* @return {string} A new form name.
*/
getFormName( $button ) {
const templateName = $button.data( 'template-name-raw' );
const formName = el.$formName.val();
if ( ! formName ) {
return templateName;
}
return activeTemplateName === formName ? templateName : formName;
},
/**
* Apply template.
*
* The final part of the select template routine.
*
* @since 1.6.9
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {jQuery} $button Use a template button object.
*/
applyTemplate( formName, template, $button ) {
el.$builder.trigger( 'wpformsTemplateSelect', template );
if ( vars.formID ) {
// Existing form.
app.selectTemplateExistingForm( formName, template, $button );
} else {
// Create a new form.
WPFormsFormTemplates.selectTemplateProcess( formName, template, $button, app.selectTemplateProcessAjax );
}
},
/**
* Select Blank template.
*
* @since 1.6.8
*
* @param {Object} e Event object.
*/
selectBlankTemplate( e ) {
e.preventDefault();
const $button = $( e.target ),
formName = el.$formName.val() || wpforms_builder.blank_form,
template = 'blank';
app.applyTemplate( formName, template, $button );
},
/**
* Select template. Existing form.
*
* @since 1.6.8
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {jQuery} $button Use a template button object.
*/
selectTemplateExistingForm( formName, template, $button ) {
$.confirm( {
title: wpforms_builder.heads_up,
content: wpforms_builder.template_confirm,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
WPFormsFormTemplates.selectTemplateProcess( formName, template, $button, app.selectTemplateProcessAjax );
},
},
cancel: {
text: wpforms_builder.cancel,
action() {
WPFormsFormTemplates.selectTemplateCancel();
},
},
},
} );
},
/**
* Select template.
*
* @since 1.6.8
* @since 1.8.2 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.selectTemplateProcess` instead.
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {jQuery} $button Use a template button object.
*/
selectTemplateProcess( formName, template, $button ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.selectTemplateProcess( formName, template, $button )" has been deprecated, please use the new "WPFormsFormTemplates.selectTemplateProcess( formName, template, $button, callback )" function instead!' );
WPFormsFormTemplates.selectTemplateProcess( formName, template, $button, app.selectTemplateProcessAjax );
},
/**
* Cancel button click routine.
*
* @since 1.6.8
* @since 1.7.7 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.selectTemplateCancel` instead.
*/
selectTemplateCancel( ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.selectTemplateCancel" has been deprecated, please use the new "WPFormsFormTemplates.selectTemplateCancel" function instead!' );
WPFormsFormTemplates.selectTemplateCancel();
},
/**
* Select template. Create or update form AJAX call.
*
* @since 1.6.8
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
*/
selectTemplateProcessAjax( formName, template ) {
WPFormsBuilder.showLoadingOverlay();
const data = {
title: formName,
action: vars.formID ? 'wpforms_update_form_template' : 'wpforms_new_form',
template,
form_id: vars.formID, // eslint-disable-line camelcase
nonce: wpforms_builder.nonce,
};
const category = $( '.wpforms-setup-templates-categories li.active' ).data( 'category' );
const subcategory = $( '.wpforms-setup-templates-subcategories li.active' ).data( 'subcategory' );
if ( category ) {
data.category = category;
}
if ( subcategory ) {
data.subcategory = subcategory;
}
if ( category === 'all' ) {
data.subcategory = 'all';
}
$.post( wpforms_builder.ajax_url, data )
.done( function( res ) {
if ( res.success ) {
// We have already warned the user that unsaved changes will be ignored.
WPFormsBuilder.setCloseConfirmation( false );
window.location.href = wpf.getQueryString( 'force_desktop_view' )
? wpf.updateQueryString( 'force_desktop_view', '1', res.data.redirect )
: res.data.redirect;
return;
}
wpf.debug( res );
if ( res.data.error_type === 'invalid_template' ) {
app.selectTemplateProcessInvalidTemplateError( res.data.message, formName );
return;
}
app.selectTemplateProcessError( res.data.message );
} )
.fail( function( xhr, textStatus ) {
wpf.debug( xhr.responseText || textStatus || '' );
app.selectTemplateProcessError( '' );
} );
},
/**
* Select template AJAX call error modal for invalid template using.
*
* @since 1.7.5.3
*
* @param {string} errorMessage Error message.
* @param {string} formName Name of the form.
*/
selectTemplateProcessInvalidTemplateError( errorMessage, formName ) {
$.alert( {
title: wpforms_builder.heads_up,
content: errorMessage,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_builder.use_default_template,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
app.selectTemplateProcessAjax( formName, 'simple-contact-form-template' );
WPFormsBuilder.hideLoadingOverlay();
},
},
cancel: {
text: wpforms_builder.cancel,
action() {
WPFormsFormTemplates.selectTemplateCancel();
WPFormsBuilder.hideLoadingOverlay();
},
},
},
} );
},
/**
* Select template AJAX call error modal.
*
* @since 1.6.8
* @since 1.8.8 Replaced error message with error title.
*
* @param {string} errorTitle Error title.
*/
selectTemplateProcessError( errorTitle ) {
$.alert( {
title: errorTitle,
content: wpforms_builder.error_select_template,
icon: 'fa fa-exclamation-circle',
type: 'orange',
buttons: {
confirm: {
text: wpforms_builder.ok,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action() {
WPFormsFormTemplates.selectTemplateCancel();
WPFormsBuilder.hideLoadingOverlay();
},
},
},
} );
},
/**
* Open required addons alert.
*
* @since 1.6.8
* @since 1.8.2 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.addonsModal` instead.
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
* @param {jQuery} $button Use a template button object.
*/
addonsModal( formName, template, $button ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.addonsModal( formName, template, $button )" has been deprecated, please use the new "WPFormsFormTemplates.addonsModal( formName, template, $button, callback )" function instead!' );
WPFormsFormTemplates.addonsModal( formName, template, $button, app.selectTemplateProcessAjax );
},
/**
* Install & Activate addons via AJAX.
*
* @since 1.6.8
* @since 1.8.2 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.installActivateAddons` instead.
*
* @param {Array} addons Addons slugs.
* @param {Object} previousModal Previous modal instance.
* @param {string} formName Name of the form.
* @param {string} template Template slug.
*/
installActivateAddons( addons, previousModal, formName, template ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.installActivateAddons( addons, previousModal, formName, template )" has been deprecated, please use the new "WPFormsFormTemplates.installActivateAddons( addons, previousModal, formName, template, callback )" function instead!' );
WPFormsFormTemplates.installActivateAddons( addons, previousModal, formName, template, app.selectTemplateProcessAjax );
},
/**
* Install & Activate addons error modal.
*
* @since 1.6.8
* @since 1.8.2 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.installActivateAddonsError` instead.
*
* @param {string} formName Name of the form.
* @param {string} template Template slug.
*/
installActivateAddonsError( formName, template ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.installActivateAddonsError( formName, template )" has been deprecated, please use the new "WPFormsFormTemplates.installActivateAddonsError( formName, template, callback )" function instead!' );
WPFormsFormTemplates.installActivateAddonsError( formName, template, app.selectTemplateProcessAjax );
},
/**
* Install & Activate single addon via AJAX.
*
* @since 1.6.8
* @since 1.8.2 Deprecated.
*
* @deprecated Use `WPFormsFormTemplates.installActivateAddonAjax` instead.
*
* @param {string} addon Addon slug.
*
* @return {Promise} jQuery ajax call promise.
*/
installActivateAddonAjax( addon ) {
console.warn( 'WARNING! Function "WPForms.Admin.Builder.Setup.installActivateAddonAjax( addon )" has been deprecated, please use the new "WPFormsFormTemplates.installActivateAddonAjax( addon )" function instead!' );
return WPFormsFormTemplates.installActivateAddonAjax( addon );
},
/**
* Initiate template processing for a new form.
*
* @since 1.6.8
*/
applyTemplateOnRequest() {
const urlParams = new URLSearchParams( window.location.search ),
templateId = urlParams.get( 'template_id' );
if (
urlParams.get( 'view' ) !== 'setup' ||
urlParams.get( 'form_id' ) ||
! templateId
) {
return;
}
el.$panel.find( '.wpforms-template .wpforms-btn[data-template="' + templateId + '"]' ).trigger( 'click' );
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );
// Initialize.
WPForms.Admin.Builder.Setup.init();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,107 @@
/* global WPForms, jQuery, Map, wpforms_builder, wpforms_builder_providers, _ */
var WPForms = window.WPForms || {};
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.Templates = WPForms.Admin.Builder.Templates || ( function( document, window, $ ) {
'use strict';
/**
* Private functions and properties.
*
* @since 1.4.8
*
* @type {Object}
*/
var __private = {
/**
* All templating functions for providers are stored here in a Map.
* Key is a template name, value - Underscore.js templating function.
*
* @since 1.4.8
*
* @type {Map}
*/
previews: new Map(),
};
/**
* Public functions and properties.
*
* @since 1.4.8
*
* @type {Object}
*/
var app = {
/**
* Start the engine. DOM is not ready yet, use only to init something.
*
* @since 1.4.8
*/
init: function() {
// Do that when DOM is ready.
$( app.ready );
},
/**
* DOM is fully loaded.
*
* @since 1.4.8
*/
ready: function() {
$( '#wpforms-panel-providers' ).trigger( 'WPForms.Admin.Builder.Templates.ready' );
},
/**
* Register and compile all templates.
* All data is saved in a Map.
*
* @since 1.4.8
*
* @param {string[]} templates Array of template names.
*/
add: function( templates ) {
templates.forEach( function( template ) {
if ( typeof template === 'string' ) {
__private.previews.set( template, wp.template( template ) );
}
} );
},
/**
* Get a templating function (to compile later with data).
*
* @since 1.4.8
*
* @param {string} template ID of a template to retrieve from a cache.
*
* @returns {*} A callable that after compiling will always return a string.
*/
get: function( template ) {
var preview = __private.previews.get( template );
if ( typeof preview !== 'undefined' ) {
return preview;
}
return function() {
return '';
};
},
};
// Provide access to public functions/properties.
return app;
} )( document, window, jQuery );
// Initialize.
WPForms.Admin.Builder.Templates.init();

View File

@@ -0,0 +1 @@
var WPForms=window.WPForms||{};WPForms.Admin=WPForms.Admin||{},WPForms.Admin.Builder=WPForms.Admin.Builder||{},WPForms.Admin.Builder.Templates=WPForms.Admin.Builder.Templates||function(e){"use strict";var r={previews:new Map},i={init:function(){e(i.ready)},ready:function(){e("#wpforms-panel-providers").trigger("WPForms.Admin.Builder.Templates.ready")},add:function(e){e.forEach(function(e){"string"==typeof e&&r.previews.set(e,wp.template(e))})},get:function(e){e=r.previews.get(e);return void 0!==e?e:function(){return""}}};return i}((document,window,jQuery)),WPForms.Admin.Builder.Templates.init();

View File

@@ -0,0 +1,157 @@
/* global wpforms_builder, Choices */
/**
* WPForms ChoicesJS utility methods for the Admin Builder.
*
* @since 1.7.9
*/
'use strict';
var WPForms = window.WPForms || {};
WPForms.Admin = WPForms.Admin || {};
WPForms.Admin.Builder = WPForms.Admin.Builder || {};
WPForms.Admin.Builder.WPFormsChoicesJS = WPForms.Admin.Builder.WPFormsChoicesJS || ( function( document, window, $ ) {
/**
* Public functions and properties.
*
* @since 1.7.9
*
* @type {object}
*/
const app = {
/**
* Setup the Select Page ChoicesJS instance.
*
* @since 1.7.9
*
* @param {object} element DOM Element where to init ChoicesJS.
* @param {object} choicesJSArgs ChoicesJS init options.
* @param {object} ajaxArgs Object containing `action` and `nonce` to perform AJAX search.
*
* @returns {Choices} ChoicesJS instance.
*/
setup: function( element, choicesJSArgs, ajaxArgs ) {
choicesJSArgs.searchEnabled = true;
choicesJSArgs.allowHTML = false; // TODO: Remove after next Choices.js release.
choicesJSArgs.searchChoices = ajaxArgs.nonce === null; // Enable searchChoices when not using AJAX.
choicesJSArgs.renderChoiceLimit = -1;
choicesJSArgs.noChoicesText = wpforms_builder.no_pages_found;
choicesJSArgs.noResultsText = wpforms_builder.no_pages_found;
const choicesJS = new Choices( element, choicesJSArgs );
if ( ajaxArgs.nonce === null ) {
return choicesJS;
}
/*
* ChoicesJS doesn't handle empty string search with it's `search` event handler,
* so we work around it by detecting empty string search with `keyup` event.
*/
choicesJS.input.element.addEventListener( 'keyup', function( ev ) {
// Only capture backspace and delete keypress that results to empty string.
if (
( ev.which !== 8 && ev.which !== 46 ) ||
ev.target.value.length > 0
) {
return;
}
app.performSearch( choicesJS, '', ajaxArgs );
} );
choicesJS.passedElement.element.addEventListener( 'search', _.debounce( function( ev ) {
// Make sure that the search term is actually changed.
if ( choicesJS.input.element.value.length === 0 ) {
return;
}
app.performSearch( choicesJS, ev.detail.value, ajaxArgs );
}, 800 ) );
return choicesJS;
},
/**
* Perform search in ChoicesJS instance.
*
* @since 1.7.9
*
* @param {Choices} choicesJS ChoicesJS instance.
* @param {string} searchTerm Search term.
* @param {object} ajaxArgs Object containing `action` and `nonce` to perform AJAX search.
*/
performSearch: function( choicesJS, searchTerm, ajaxArgs ) {
if ( ! ajaxArgs.action || ! ajaxArgs.nonce ) {
return;
}
app.displayLoading( choicesJS );
const requestSearchPages = app.ajaxSearchPages( ajaxArgs.action, searchTerm, ajaxArgs.nonce );
requestSearchPages.done( function( response ) {
choicesJS.setChoices( response.data, 'value', 'label', true );
} );
},
/**
* Display "Loading" in ChoicesJS instance.
*
* @since 1.7.9
*
* @param {Choices} choicesJS ChoicesJS instance.
*/
displayLoading: function( choicesJS ) {
choicesJS.setChoices(
[
{ value: '', label: `${wpforms_builder.loading}...`, disabled: true },
],
'value',
'label',
true
);
},
/**
* Perform AJAX search request.
*
* @since 1.7.9
*
* @param {string} action Action to be used when doing ajax request for search.
* @param {string} searchTerm Search term.
* @param {string} nonce Nonce to be used when doing ajax request.
*
* @returns {Promise} jQuery ajax call promise.
*/
ajaxSearchPages: function( action, searchTerm, nonce ) {
return $.get(
wpforms_builder.ajax_url,
{
action: action,
search: searchTerm,
_wpnonce: nonce,
}
).fail(
function( err ) {
console.error( err );
}
);
},
};
// Provide access to public functions/properties.
return app;
}( document, window, jQuery ) );

View File

@@ -0,0 +1 @@
"use strict";var WPForms=window.WPForms||{};WPForms.Admin=WPForms.Admin||{},WPForms.Admin.Builder=WPForms.Admin.Builder||{},WPForms.Admin.Builder.WPFormsChoicesJS=WPForms.Admin.Builder.WPFormsChoicesJS||function(r){const i={setup:function(e,n,o){n.searchEnabled=!0,n.allowHTML=!1,n.searchChoices=null===o.nonce,n.renderChoiceLimit=-1,n.noChoicesText=wpforms_builder.no_pages_found,n.noResultsText=wpforms_builder.no_pages_found;const r=new Choices(e,n);return null!==o.nonce&&(r.input.element.addEventListener("keyup",function(e){8!==e.which&&46!==e.which||0<e.target.value.length||i.performSearch(r,"",o)}),r.passedElement.element.addEventListener("search",_.debounce(function(e){0!==r.input.element.value.length&&i.performSearch(r,e.detail.value,o)},800))),r},performSearch:function(n,e,o){o.action&&o.nonce&&(i.displayLoading(n),i.ajaxSearchPages(o.action,e,o.nonce).done(function(e){n.setChoices(e.data,"value","label",!0)}))},displayLoading:function(e){e.setChoices([{value:"",label:wpforms_builder.loading+"...",disabled:!0}],"value","label",!0)},ajaxSearchPages:function(e,n,o){return r.get(wpforms_builder.ajax_url,{action:e,search:n,_wpnonce:o}).fail(function(e){console.error(e)})}};return i}((document,window,jQuery));