/* global wpforms_builder, wpf, jconfirm, wpforms_panel_switch, Choices, WPForms */
/* global WPFormsFormEmbedWizard, wpCookies, tinyMCE, WPFormsUtils, List, wpforms_preset_choices */
// noinspection TypeScriptUMDGlobal
* @param window.Jconfirm.prototype._updateContentMaxHeight
* @param wpforms_builder.allow_deny_lists_intersect
* @param wpforms_builder.allow_only_email_fields
* @param wpforms_builder.allow_only_one_email
* @param wpforms_builder.are_you_sure_to_close
* @param wpforms_builder.bulk_add_button
* @param wpforms_builder.bulk_add_heading
* @param wpforms_builder.bulk_add_hide
* @param wpforms_builder.bulk_add_placeholder
* @param wpforms_builder.bulk_add_presets_show
* @param wpforms_builder.bulk_add_show
* @param wpforms_builder.choices_icons
* @param wpforms_builder.choices_images
* @param wpforms_builder.date_select_day
* @param wpforms_builder.date_select_month
* @param wpforms_builder.delete_choice_confirm
* @param wpforms_builder.duplicate_confirm
* @param wpforms_builder.duplicate_copy
* @param wpforms_builder.dynamic_choices.empty_message
* @param wpforms_builder.dynamic_choices.limit_message
* @param wpforms_builder.empty_email_address
* @param wpforms_builder.empty_label
* @param wpforms_builder.entry_preview_default_notice
* @param wpforms_builder.entry_preview_require_page_break
* @param wpforms_builder.entry_preview_require_previous_button
* @param wpforms_builder.error_choice
* @param wpforms_builder.error_contact_support
* @param wpforms_builder.error_number_slider_increment
* @param wpforms_builder.error_save_form
* @param wpforms_builder.exit_confirm
* @param wpforms_builder.field_locked_no_delete_msg
* @param wpforms_builder.field_locked_no_duplicate_msg
* @param wpforms_builder.file_upload.preview_hint
* @param wpforms_builder.file_upload.preview_title_plural
* @param wpforms_builder.file_upload.preview_title_single
* @param wpforms_builder.icon_choices.choice_empty_label_tpl
* @param wpforms_builder.icon_choices.default_color
* @param wpforms_builder.icon_choices.default_icon
* @param wpforms_builder.icon_choices.default_icon_style
* @param wpforms_builder.icon_choices.delete_confirm
* @param wpforms_builder.icon_choices.field_locked
* @param wpforms_builder.icon_choices.icons_per_page
* @param wpforms_builder.icon_choices.is_active
* @param wpforms_builder.icon_choices.is_installed
* @param wpforms_builder.icon_choices.strings.icon_picker_description
* @param wpforms_builder.icon_choices.strings.icon_picker_not_found
* @param wpforms_builder.icon_choices.strings.icon_picker_search_placeholder
* @param wpforms_builder.icon_choices.strings.icon_picker_title
* @param wpforms_builder.icon_choices.strings.install_content
* @param wpforms_builder.icon_choices.strings.install_error_content
* @param wpforms_builder.icon_choices.strings.install_prompt_content
* @param wpforms_builder.icon_choices.strings.install_success_content
* @param wpforms_builder.icon_choices.strings.install_title
* @param wpforms_builder.icon_choices.strings.reinstall_prompt_content
* @param wpforms_builder.layout_selector_column
* @param wpforms_builder.layout_selector_hide
* @param wpforms_builder.layout_selector_layout
* @param wpforms_builder.layout_selector_show
* @param wpforms_builder.notification_by_status_enable_alert
* @param wpforms_builder.notification_by_status_switch_alert
* @param wpforms_builder.number_slider_error_valid_default_value
* @param wpforms_builder.payment_choice_empty_label_tpl
* @param wpforms_builder.preview_url
* @param wpforms_builder.pro
* @param wpforms_builder.redirect_url_field_error
* @param wpforms_builder.restricted_default_email
* @param wpforms_builder.restricted_rules
* @param wpforms_builder.revision_update_confirm
* @param wpforms_builder.save_exit
* @param wpforms_builder.scrollbars_css_url
* @param wpforms_builder.shortcuts_modal_msg
* @param wpforms_builder.shortcuts_modal_title
* @param wpforms_builder.smart_tags_disabled_for_confirmations
* @param wpforms_builder.smart_tags_dropdown_mce_icon
* @param wpforms_builder.smart_tags_hide
* @param wpforms_builder.smart_tags_show
* @param wpforms_builder.something_went_wrong
* @param wpforms_builder.template_modal_msg
* @param wpforms_builder.template_modal_title
* @param wpforms_builder.upload_image_button
* @param wpforms_builder.upload_image_extensions
* @param wpforms_builder.upload_image_extensions_error
* @param wpforms_builder.upload_image_remove
* @param wpforms_builder.upload_image_title
* @param wpforms_builder.wpforms_builder.bulk_add_presets_hide
/* noinspection JSUnusedLocalSymbols */
/* eslint-disable no-unused-expressions, no-shadow */
// noinspection ES6ConvertVarToLetConst
var WPFormsBuilder = window.WPFormsBuilder || ( function( document, window, $ ) { // eslint-disable-line no-var
* Whether to show the close confirmation dialog or not.
let closeConfirmation = true;
// noinspection JSUnusedGlobalSymbols
* @property {(selector: string) => JQ} closest Closest function.
* @property {(prop: string) => string} css Css function.
* @property {(prop: string) => string} data Data function.
* @property {() => JQ} fadeIn FadeIn function.
* @property {(selector: string) => JQ} find Find function.
* @property {(text: string) => undefined} insertAtCaret InsertAtCaret function.
* @property {(selector: string) => JQ} next Next function.
* @property {() => JQ} slideDown SlideDown function.
* @property {() => JQ} slideToggle SlideToggle function.
* @property {() => JQ} slideUp SlideUp function.
* @property {() => JQ} stop Stop function.
* @param {(selector: string) => JQ} $ The jQuery-compatible function.
* @typedef {Object} jqXHR
* @property {(callback: (data: any, textStatus: string, jqXHR: jqXHR) => void) => jqXHR} done Done function.
* @typedef {Object} Options
* @property {string|number} position Position.
* @typedef {Object} Modal
* @property {jQuery} $title Title.
* @property {jQuery} $content Content.
/* eslint-disable camelcase */
spinner: '<i class="wpforms-loading-spinner"></i>',
spinnerInline: '<i class="wpforms-loading-spinner wpforms-loading-inline"></i>',
tinymce: { toolbar1: 'bold,italic,underline,blockquote,strikethrough,bullist,numlist,alignleft,aligncenter,alignright,undo,redo,link' },
choicesLimit: 20, // Choices limit for fields different from Dropdown.
choicesLimitLong: 250, // Choices limit for Dropdown field.
wpforms_panel_switch = true;
$( 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 );
$( window ).on( 'beforeunload', function() {
if ( ! that.formIsSaved() && closeConfirmation ) {
return wpforms_builder.are_you_sure_to_close;
* @since 1.7.9 Added `wpformsBuilderReady` hook.
* @return {false|void} False if default event is prevented.
// Trigger initial save for new forms.
if ( wpf.getQueryString( 'newform' ) ) {
const panel = $( '#wpforms-panels-toggle .active' ).data( 'panel' );
// Render form preview on the Revisions panel if the panel is active.
if ( panel === 'revisions' ) {
app.updateRevisionPreview();
// Allow callbacks to prevent making Form Builder ready...
const event = WPFormsUtils.triggerEvent( $builder, 'wpformsBuilderReady' );
// ...by triggering `event.preventDefault()`.
if ( event.isDefaultPrevented() ) {
// Hide the loading overlay and make the Form Builder ready to use.
app.hideLoadingOverlay();
app.determineActiveSections();
// Confirmations' initial setup.
app.confirmationsSetup();
WPFormsUtils.triggerEvent( $builder, 'wpformsBuilderConfirmationsReady' );
// Maybe display informational modal.
// noinspection JSUnresolvedReference, EqualityComparisonWithCoercionJS
if ( wpforms_builder.template_modal_display == '1' && 'fields' === wpf.getQueryString( 'view' ) ) { // eslint-disable-line
title: wpforms_builder.template_modal_title,
content: wpforms_builder.template_modal_msg,
icon: 'fa fa-info-circle',
text: wpforms_builder.close,
// Cache builder element.
$builder = $( '#wpforms-builder' );
browser.isWindows = /Win/.test( navigator.userAgent );
browser.isLinux = /Linux/.test( navigator.userAgent );
browser.isMac = /Mac/.test( navigator.userAgent );
elements.$helpButton = $( '#wpforms-help' );
elements.$previewButton = $( '#wpforms-preview-btn' );
elements.$embedButton = $( '#wpforms-embed' );
elements.$saveButton = $( '#wpforms-save' );
elements.$exitButton = $( '#wpforms-exit' );
elements.$noFieldsOptions = $( '#wpforms-panel-fields .wpforms-no-fields-holder .no-fields' );
elements.$noFieldsPreview = $( '#wpforms-panel-fields .wpforms-no-fields-holder .no-fields-preview' );
elements.$formPreview = $( '#wpforms-panel-fields .wpforms-preview-wrap' );
elements.$revisionPreview = $( '#wpforms-panel-revisions .wpforms-panel-content' );
elements.defaultEmailSelector = '.wpforms-field-option-email .wpforms-field-option-row-default_value input';
elements.$defaultEmail = $( elements.defaultEmailSelector );
elements.$focusOutTarget = null;
elements.$nextFieldId = $( '#wpforms-field-id' );
elements.$addFieldsTab = $( '#add-fields a' );
elements.$fieldOptions = $( '#wpforms-field-options' );
elements.$fieldsPreviewWrap = $( '#wpforms-panel-fields .wpforms-panel-content-wrap' );
elements.$sortableFieldsWrap = $( '#wpforms-panel-fields .wpforms-field-wrap' );
elements.$addFieldsButtons = $( '.wpforms-add-fields-button' ).not( '.not-draggable' ).not( '.warning-modal' ).not( '.education-modal' );
elements.$fieldsSidebar = $( '#wpforms-panel-fields .wpforms-add-fields' );
elements.$searchInput = $( '#wpforms-search-fields-input' );
elements.$sidebarToggle = $( '.wpforms-panels .wpforms-panel-sidebar-content .wpforms-panel-sidebar-toggle' );
ready() { // eslint-disable-line max-lines-per-function
if ( app.isVisitedViaBackButton() ) {
// Add `_wp_http_referer` to the data of every AJAX request.
// eslint-disable-next-line camelcase
_wp_http_referer: wpf.updateQueryString( '_wp_http_referer', null ),
// Remove Embed button if builder opened in the popup.
if ( app.isBuilderInPopup() ) {
elements.$embedButton.remove();
elements.$previewButton.addClass( 'wpforms-alone' );
// Setup/cache some vars not available before
s.formID = $( '#wpforms-builder-form' ).data( 'id' );
s.pagebreakTop = $( '.wpforms-pagebreak-top' ).length;
s.pagebreakBottom = $( '.wpforms-pagebreak-bottom' ).length;
// Disable implicit submission for every form inside the builder.
// All form values are managed by JS and should not be submitted by pressing Enter.
$builder.on( 'keypress', '#wpforms-builder-form :input:not(textarea)', function( e ) {
if ( e.keyCode === 13 ) {
app.loadEntryPreviewFields();
// Drag and drop sortable elements.
app.fieldChoiceSortable( 'select' );
app.fieldChoiceSortable( 'radio' );
app.fieldChoiceSortable( 'checkbox' );
app.fieldChoiceSortable( 'payment-multiple' );
app.fieldChoiceSortable( 'payment-checkbox' );
app.fieldChoiceSortable( 'payment-select' );
// Set field group visibility.
$( '.wpforms-add-fields-group' ).each( function() {
app.fieldGroupToggle( $( this ), 'load' );
// Trim long form titles.
// Hide/Show CAPTCHA in form.
// Notification settings.
app.notificationToggle();
app.notificationsByStatusAlerts();
// Secret builder hotkeys.
// jquery-confirm defaults.
backgroundDismiss: false,
animateFromElement: false,
content: wpforms_builder.something_went_wrong,
app.dropdownField.init();
app.disabledFields.init();
app.checkEmptyDynamicChoices();
app.initSomeFieldOptions();
wpf.initializeChoicesEventHandlers();
checkEmptyDynamicChoices() {
const choices = wpf.orders.choices || {};
if ( ! Object.keys( choices ).length ) {
wpf.orders.fields.forEach( function( fieldId ) {
const isDynamic = app.dropdownField.helpers.isDynamicChoices( fieldId );
const $fieldPreview = $( '#wpforms-field-' + fieldId );
const type = app.dropdownField.helpers.getDynamicChoicesOptionType( fieldId );
const source = app.dropdownField.helpers.getDynamicChoicesOptionSource( fieldId );
const isModern = app.dropdownField.helpers.isDynamicChoicesOptionModern( fieldId );
? $fieldPreview.find( '.has-no-choices' ).length
: $fieldPreview.find( '.primary-input option:not(.placeholder), .primary-input li' ).length === 0;
if ( isModern && ! isEmpty ) {
const placeholder = $( '#wpforms-field-option-' + fieldId + '-placeholder' ).val();
const choices = app.dropdownField.helpers.getInitialChoices( fieldId );
isEmpty = choices.length === 1 && choices[ 0 ].label === placeholder && choices[ 0 ].placeholder === true;
app.emptyChoicesNotice( fieldId, source, type );
* Load Microsoft Windows specific stylesheet.
href: wpforms_builder.scrollbars_css_url,
* Builder was visited via the back button in the browser.
* @return {boolean} True if the builder was visited via back button in browser.
isVisitedViaBackButton() {
let isVisitedViaBackButton = false;
performance.getEntriesByType( 'navigation' ).forEach( function( nav ) {
if ( nav.type === 'back_forward' ) {
isVisitedViaBackButton = true;
return isVisitedViaBackButton;