From cd0f322137c093477d61b78e8bab9cbe121e39b8 Mon Sep 17 00:00:00 2001 From: Abdi Tolessa <41271840+AbdiTolesa@users.noreply.github.com> Date: Fri, 31 Oct 2025 17:46:31 +0300 Subject: [PATCH 01/45] Add new upsells in Lite for missing Pro features --- classes/controllers/FrmFieldsController.php | 2 ++ classes/views/frm-fields/back-end/settings.php | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/classes/controllers/FrmFieldsController.php b/classes/controllers/FrmFieldsController.php index 836006836d..049f3d0df7 100644 --- a/classes/controllers/FrmFieldsController.php +++ b/classes/controllers/FrmFieldsController.php @@ -362,6 +362,8 @@ public static function load_single_field_settings( $atts ) { $field['placeholder'] = implode( ', ', $field['placeholder'] ); } + $pro_is_installed = FrmAppHelper::pro_is_installed(); + $no_allow = ! $pro_is_installed ? 'frm_noallow' : ''; include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/settings.php'; } diff --git a/classes/views/frm-fields/back-end/settings.php b/classes/views/frm-fields/back-end/settings.php index ca29a07420..35374689be 100644 --- a/classes/views/frm-fields/back-end/settings.php +++ b/classes/views/frm-fields/back-end/settings.php @@ -102,22 +102,26 @@
'+e.message+"
Imported '+r.data.name+"
",e.find(".status").prepend(n),e.find(".status").show(),O.importQueue=jQuery.grep(O.importQueue,function(e){return e!=t}),O.imported++,0===O.importQueue.length?(e.find(".process-count").hide(),e.find(".forms-completed").text(O.imported),e.find(".process-completed").show()):(e.find(".form-current").text(O.imported+1),Zi(e)))})}function eo(e){e.preventDefault();var t=!1,r=jQuery('input[name="frm_export_forms[]"]');jQuery('input[name="frm_export_forms[]"]:checked').val()||(r.closest(".frm-table-box").addClass("frm_blank_field"),t="stop");var n=jQuery('input[name="type[]"]');if(jQuery('input[name="type[]"]:checked').val()||"checkbox"!==n.attr("type")||(n.closest("p").addClass("frm_blank_field"),t="stop"),"stop"===t)return!1;e.stopPropagation(),this.submit()}function to(){var e=jQuery(this).closest(".frm_blank_field");if(void 0!==e){var t=this.name;("type[]"===t&&jQuery('input[name="type[]"]:checked').val()||"frm_export_forms[]"===t&&jQuery(this).val())&&e.removeClass("frm_blank_field")}}function ro(){null!==jQuery(this).val().match(/\.csv$/i)?jQuery(".show_csv").fadeIn():jQuery(".show_csv").fadeOut()}function no(){var e=document.querySelector('select[name="format"]');return e?e.value:""}function io(e){var t,r,n=e.target.value;ao(n),oo.call(e.target),t=n,r=document.getElementById("frm-export-select-all"),"csv"===t?(r.checked=!1,r.disabled=!0):r.disabled=!1}function oo(){var e=jQuery(this),t=e.find(":selected"),r=t.data("support"),n=r.indexOf("|");jQuery('input[name="type[]"]').each(function(){this.checked=!1,r.indexOf(this.value)>=0?(this.disabled=!1,-1===n&&(this.checked=!0)):this.disabled=!0}),"csv"===e.val()?(jQuery(".csv_opts").show(),jQuery(".xml_opts").hide()):(jQuery(".csv_opts").hide(),jQuery(".xml_opts").show());var i=t.data("count"),o=jQuery('input[name="frm_export_forms[]"]');"single"===i?(o.prop("multiple",!1),o.prop("checked",!1)):(o.prop("multiple",!0),o.prop("disabled",!1)),e.trigger("change")}function ao(e){if(""!==e){var t=document.querySelectorAll(".frm-is-repeater");t.length&&("csv"===e?t.forEach(function(e){e.classList.remove("frm_hidden")}):t.forEach(function(e){e.classList.add("frm_hidden")}),xo.call(document.querySelector(".frm-auto-search")))}}function lo(){var e=jQuery("select[name=format]").find(":selected").data("count"),t=jQuery('input[name="frm_export_forms[]"]');"single"===e&&this.checked?(t.prop("disabled",!0),this.removeAttribute("disabled")):t.prop("disabled",!1)}function so(){jQuery(".frm_multiselect").hide().each(frmDom.bootstrap.multiselect.init)}function co(e){e.preventDefault(),mo(this,"frm_multiple_addons")}function fo(e){e.preventDefault(),mo(this,"frm_activate_addon")}function uo(e){e.preventDefault(),mo(this,"frm_install_addon")}function mo(e,t){r(105).toggleAddonState(e,t)}function _o(){go()}function po(e){!function(e,t,r){var n=jQuery("#frm_leave_email_error");n.removeClass("frm_hidden").attr("frm-error",r),jQuery("#frm_leave_email").one("keyup",function(){n.addClass("frm_hidden")})}(0,0,e)}function go(){var e=document.getElementById("frmapi-email-form");jQuery.ajax({dataType:"json",url:e.getAttribute("data-url"),success:function(t){var r=t.renderedHtml;r=r.replace(/]*(formidableforms.css|action=frmpro_css)[^>]*>/gi,""),e.innerHTML=r}})}function ho(e){frmDom.autocomplete.initSelectionAutocomplete(e)}function yo(e){var t=this.parentNode.parentNode,r=t.elements.type.value;e.preventDefault(),this.classList.add("frm_loading_button"),bo(t,r,this)}function vo(e){var t=this.elements.type.value,r=this.querySelector("button");e.preventDefault(),r.classList.add("frm_loading_button"),bo(this,t,r)}function bo(e,t,r){var n=function(e){var t,r,n={},i=e.elements;for(r=0;r' + response.message + '
' + res.data.name + ': ' + res.data.msg + '
'; + } else { + statusUpdate = 'Imported ' + res.data.name + '
'; + } + $processSettings.find('.status').prepend(statusUpdate); + $processSettings.find('.status').show(); + + // Remove this form ID from the queue. + s.importQueue = jQuery.grep(s.importQueue, function (value) { + return value != formID; + }); + s.imported++; + if (s.importQueue.length === 0) { + $processSettings.find('.process-count').hide(); + $processSettings.find('.forms-completed').text(s.imported); + $processSettings.find('.process-completed').show(); + } else { + // Import next form in the queue. + $processSettings.find('.form-current').text(s.imported + 1); + importForm($processSettings); + } + } + }); + } + function validateExport(e) { + /*jshint validthis:true */ + e.preventDefault(); + var s = false; + var $exportForms = jQuery('input[name="frm_export_forms[]"]'); + if (!jQuery('input[name="frm_export_forms[]"]:checked').val()) { + $exportForms.closest('.frm-table-box').addClass('frm_blank_field'); + s = 'stop'; + } + var $exportType = jQuery('input[name="type[]"]'); + if (!jQuery('input[name="type[]"]:checked').val() && $exportType.attr('type') === 'checkbox') { + $exportType.closest('p').addClass('frm_blank_field'); + s = 'stop'; + } + if (s === 'stop') { + return false; + } + e.stopPropagation(); + this.submit(); + } + function removeExportError() { + /*jshint validthis:true */ + var t = jQuery(this).closest('.frm_blank_field'); + if (typeof t === 'undefined') { + return; + } + var $thisName = this.name; + if ($thisName === 'type[]' && jQuery('input[name="type[]"]:checked').val()) { + t.removeClass('frm_blank_field'); + } else if ($thisName === 'frm_export_forms[]' && jQuery(this).val()) { + t.removeClass('frm_blank_field'); + } + } + function checkCSVExtension() { + /*jshint validthis:true */ + var f = jQuery(this).val(); + var re = /\.csv$/i; + if (f.match(re) !== null) { + jQuery('.show_csv').fadeIn(); + } else { + jQuery('.show_csv').fadeOut(); + } + } + function getExportOption() { + var exportFormatSelect = document.querySelector('select[name="format"]'); + if (exportFormatSelect) { + return exportFormatSelect.value; + } + return ''; + } + function exportTypeChanged(event) { + var value = event.target.value; + showOrHideRepeaters(value); + checkExportTypes.call(event.target); + checkSelectedAllFormsCheckbox(value); + } + function checkSelectedAllFormsCheckbox(exportType) { + var selectAllCheckbox = document.getElementById('frm-export-select-all'); + if (exportType === 'csv') { + selectAllCheckbox.checked = false; + selectAllCheckbox.disabled = true; + } else { + selectAllCheckbox.disabled = false; + } + } + function checkExportTypes() { + /*jshint validthis:true */ + var $dropdown = jQuery(this); + var $selected = $dropdown.find(':selected'); + var s = $selected.data('support'); + var multiple = s.indexOf('|'); + jQuery('input[name="type[]"]').each(function () { + this.checked = false; + if (s.indexOf(this.value) >= 0) { + this.disabled = false; + if (multiple === -1) { + this.checked = true; + } + } else { + this.disabled = true; + } + }); + if ($dropdown.val() === 'csv') { + jQuery('.csv_opts').show(); + jQuery('.xml_opts').hide(); + } else { + jQuery('.csv_opts').hide(); + jQuery('.xml_opts').show(); + } + var c = $selected.data('count'); + var exportField = jQuery('input[name="frm_export_forms[]"]'); + if (c === 'single') { + exportField.prop('multiple', false); + exportField.prop('checked', false); + } else { + exportField.prop('multiple', true); + exportField.prop('disabled', false); + } + $dropdown.trigger('change'); + } + function showOrHideRepeaters(exportOption) { + if (exportOption === '') { + return; + } + var repeaters = document.querySelectorAll('.frm-is-repeater'); + if (!repeaters.length) { + return; + } + if (exportOption === 'csv') { + repeaters.forEach(function (form) { + form.classList.remove('frm_hidden'); + }); + } else { + repeaters.forEach(function (form) { + form.classList.add('frm_hidden'); + }); + } + searchContent.call(document.querySelector('.frm-auto-search')); + } + function preventMultipleExport() { + var type = jQuery('select[name=format]'), + selected = type.find(':selected'), + count = selected.data('count'), + exportField = jQuery('input[name="frm_export_forms[]"]'); + if (count === 'single') { + // Disable all other fields to prevent multiple selections. + if (this.checked) { + exportField.prop('disabled', true); + this.removeAttribute('disabled'); + } else { + exportField.prop('disabled', false); + } + } else { + exportField.prop('disabled', false); + } + } + function initiateMultiselect() { + jQuery('.frm_multiselect').hide().each(frmDom.bootstrap.multiselect.init); + } + + /* Addons page */ + function installMultipleAddons(e) { + e.preventDefault(); + toggleAddonState(this, 'frm_multiple_addons'); + } + function activateAddon(e) { + e.preventDefault(); + toggleAddonState(this, 'frm_activate_addon'); + } + function installAddon(e) { + e.preventDefault(); + toggleAddonState(this, 'frm_install_addon'); + } + function toggleAddonState(clicked, action) { + var addonState = __webpack_require__(/*! ./addon-state */ "./js/src/admin/addon-state.js"); + addonState.toggleAddonState(clicked, action); + } + function installAddonWithCreds(e) { + // Prevent the default action, let the user know we are attempting to install again and go with it. + e.preventDefault(); + + // Now let's make another Ajax request once the user has submitted their credentials. + var proceed = jQuery(this); + var el = proceed.parent().parent(); + var plugin = proceed.attr('rel'); + proceed.addClass('frm_loading_button'); + jQuery.ajax({ + url: ajaxurl, + type: 'POST', + async: true, + cache: false, + dataType: 'json', + data: { + action: 'frm_install_addon', + nonce: frmAdminJs.nonce, + plugin: plugin, + hostname: el.find('#hostname').val(), + username: el.find('#username').val(), + password: el.find('#password').val() + }, + success: function success(response) { + var _response$data, _response; + response = (_response$data = (_response = response) === null || _response === void 0 ? void 0 : _response.data) !== null && _response$data !== void 0 ? _response$data : response; + var error = extractErrorFromAddOnResponse(response); + if (error) { + addonError(error, el, proceed); + return; + } + afterAddonInstall(response, proceed, message, el); + }, + error: function error() { + proceed.removeClass('frm_loading_button'); + } + }); + } + function afterAddonInstall(response, button, message, el, saveAndReload) { + var action = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'frm_activate_addon'; + var addonState = __webpack_require__(/*! ./addon-state */ "./js/src/admin/addon-state.js"); + addonState.afterAddonInstall(response, button, message, el, saveAndReload, action); + } + function extractErrorFromAddOnResponse(response) { + var addonState = __webpack_require__(/*! ./addon-state */ "./js/src/admin/addon-state.js"); + return addonState.extractErrorFromAddOnResponse(response); + } + function addonError(response, el, button) { + var addonState = __webpack_require__(/*! ./addon-state */ "./js/src/admin/addon-state.js"); + addonState.addonError(response, el, button); + } + + /* Templates */ + function showActiveCampaignForm() { + loadApiEmailForm(); + } + function handleApiFormError(inputId, errorId, type, message) { + var $error = jQuery(errorId); + $error.removeClass('frm_hidden').attr('frm-error', type); + if (typeof message !== 'undefined') { + $error.find('span[frm-error="' + type + '"]').text(message); + } + jQuery(inputId).one('keyup', function () { + $error.addClass('frm_hidden'); + }); + } + function handleEmailAddressError(type) { + handleApiFormError('#frm_leave_email', '#frm_leave_email_error', type); + } + function loadApiEmailForm() { + var formContainer = document.getElementById('frmapi-email-form'); + jQuery.ajax({ + dataType: 'json', + url: formContainer.getAttribute('data-url'), + success: function success(json) { + var form = json.renderedHtml; + form = form.replace(/]*(formidableforms.css|action=frmpro_css)[^>]*>/gi, ''); + formContainer.innerHTML = form; + } + }); + } + function initAutocomplete(container) { + frmDom.autocomplete.initSelectionAutocomplete(container); + } + function nextInstallStep(thisStep) { + thisStep.classList.add('frm_grey'); + thisStep.nextElementSibling.classList.remove('frm_grey'); + } + function installTemplateFieldset(e) { + /*jshint validthis:true */ + var fieldset = this.parentNode.parentNode, + action = fieldset.elements.type.value, + button = this; + e.preventDefault(); + button.classList.add('frm_loading_button'); + installNewForm(fieldset, action, button); + } + function installTemplate(e) { + /*jshint validthis:true */ + var action = this.elements.type.value, + button = this.querySelector('button'); + e.preventDefault(); + button.classList.add('frm_loading_button'); + installNewForm(this, action, button); + } + function installNewForm(form, action, button) { + var formData = formToData(form); + var formName = formData.template_name; + var formDesc = formData.template_desc; + var link = form.elements.link.value; + var data = { + action: action, + xml: link, + name: formName, + desc: formDesc, + form: JSON.stringify(formData), + nonce: frmGlobal.nonce + }; + var hookName = 'frm_before_install_new_form'; + var filterArgs = { + formData: formData + }; + data = wp.hooks.applyFilters(hookName, data, filterArgs); + postAjax(data, function (response) { + if (typeof response.redirect !== 'undefined') { + var redirect = response.redirect; + if (typeof form.elements.redirect === 'undefined') { + window.location = redirect; + } else { + var href = document.getElementById('frm-redirect-link'); + if (typeof link !== 'undefined' && href !== null) { + // Show the next installation step. + href.setAttribute('href', redirect); + href.classList.remove('frm_grey', 'disabled'); + nextInstallStep(form.parentNode.parentNode); + button.classList.add('frm_grey', 'disabled'); + } + } + } else { + jQuery('.spinner').css('visibility', 'hidden'); + + // Show response.message + if ('string' === typeof response.message) { + showInstallFormErrorModal(response.message); + } + } + button.classList.remove('frm_loading_button'); + }); + } + function showInstallFormErrorModal(message) { + var modalContent = div(message); + modalContent.style.padding = '20px 40px'; + var modal = frmDom.modal.maybeCreateModal('frmInstallFormErrorModal', { + title: __('Unable to install template', 'formidable'), + content: modalContent + }); + modal.classList.add('frm_common_modal'); + } + function handleCaptchaTypeChange(e) { + var thresholdContainer = document.getElementById('frm_captcha_threshold_container'); + if (thresholdContainer) { + thresholdContainer.classList.toggle('frm_hidden', 'v3' !== e.target.value); + } + } + function trashTemplate(e) { + /*jshint validthis:true */ + var id = this.getAttribute('data-id'); + e.preventDefault(); + data = { + action: 'frm_forms_trash', + id: id, + nonce: frmGlobal.nonce + }; + postAjax(data, function () { + var card = document.getElementById('frm-template-custom-' + id); + fadeOut(card, function () { + card.parentNode.removeChild(card); + }); + }); + } + function searchContent() { + /*jshint validthis:true */ + var i, + regEx = false, + searchText = this.value.toLowerCase(), + toSearch = this.getAttribute('data-tosearch'), + items = document.getElementsByClassName(toSearch); + if (this.tagName === 'SELECT') { + searchText = selectedOptions(this); + searchText = searchText.join('|').toLowerCase(); + regEx = true; + } + if (toSearch === 'frm-action' && searchText !== '') { + var addons = document.getElementById('frm_email_addon_menu').classList; + addons.remove('frm-all-actions'); + addons.add('frm-limited-actions'); + } + for (i = 0; i < items.length; i++) { + var innerText = items[i].innerText.toLowerCase(); + var itemCanBeShown = !(getExportOption() === 'xml' && items[i].classList.contains('frm-is-repeater')); + if (searchText === '') { + if (itemCanBeShown && checkContextualShortcode(items[i])) { + items[i].classList.remove('frm_hidden'); + } + items[i].classList.remove('frm-search-result'); + } else if (regEx && new RegExp(searchText).test(innerText) || innerText.indexOf(searchText) >= 0 || textMatchesPlural(innerText, searchText)) { + if (itemCanBeShown && checkContextualShortcode(items[i])) { + items[i].classList.remove('frm_hidden'); + } + items[i].classList.add('frm-search-result'); + } else { + items[i].classList.add('frm_hidden'); + items[i].classList.remove('frm-search-result'); + } + } + + // Updates the visibility of category headings based on search results. + updateCatHeadingVisibility(); + jQuery(this).trigger('frmAfterSearch'); + } + + /** + * Allow a search for "signatures" to still match "signature" for example when searching fields. + * + * @since 6.15 + * + * @param {string} text The text in the element we are checking for a match. + * @param {string} searchText The text value that is being searched. + * @return {boolean} + */ + function textMatchesPlural(text, searchText) { + if (searchText === 's') { + // Don't match everything when just "s" is searched. + return false; + } + if (text[text.length - 1] === 's') { + // Do not match something with double s if the text already ends in s. + return false; + } + return (text + 's').indexOf(searchText) >= 0; + } + + /** + * Updates the visibility of category headings based on search results. + * If all associated fields are hidden (indicating no search matches), + * the heading is hidden. + * + * @since 6.4.1 + */ + function updateCatHeadingVisibility() { + var insertFieldsElement = document.querySelector('#frm-insert-fields'); + if (!insertFieldsElement) { + return; + } + var headingElements = insertFieldsElement.querySelectorAll(':scope > .frm-with-line'); + headingElements.forEach(function (heading) { + var fieldsListElement = heading.nextElementSibling; + if (!fieldsListElement) { + return; + } + var listItemElements = fieldsListElement.querySelectorAll(':scope > li.frmbutton'); + var allHidden = Array.from(listItemElements).every(function (li) { + return li.classList.contains('frm_hidden'); + }); + + // Add or remove class based on `allHidden` condition + heading.classList.toggle('frm_hidden', allHidden); + }); + } + function stopPropagation(e) { + e.stopPropagation(); + } + + /* Helpers */ + + function selectedOptions(select) { + var opt, + result = [], + options = select && select.options; + for (var _i13 = 0, iLen = options.length; _i13 < iLen; _i13++) { + opt = options[_i13]; + if (opt.selected) { + result.push(opt.value); + } + } + return result; + } + function triggerEvent(element, event) { + var evt = document.createEvent('HTMLEvents'); + evt.initEvent(event, false, true); + element.dispatchEvent(evt); + } + function postAjax(data, success) { + var response; + var xmlHttp = new XMLHttpRequest(); + var params = typeof data === 'string' ? data : Object.keys(data).map(function (k) { + return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]); + }).join('&'); + xmlHttp.open('post', ajaxurl, true); + xmlHttp.onreadystatechange = function () { + if (xmlHttp.readyState > 3 && xmlHttp.status == 200) { + response = xmlHttp.responseText; + try { + response = JSON.parse(response); + } catch (e) { + // The response may not be JSON, so just return it. + } + success(response); + } + }; + xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + xmlHttp.send(params); + return xmlHttp; + } + function fadeOut(element, success) { + element.classList.add('frm-fade'); + setTimeout(success, 1000); + } + function invisible(classes) { + jQuery(classes).css('visibility', 'hidden'); + } + function visible(classes) { + jQuery(classes).css('visibility', 'visible'); + } + function initModal(id, width) { + var upgradePopup = __webpack_require__(/*! ./upgrade-popup */ "./js/src/admin/upgrade-popup.js"); + return upgradePopup.initModal(id, width); + } + function toggle(cname, id) { + if (id === '#') { + var cont = document.getElementById(cname); + var hidden = cont.style.display; + if (hidden === 'none') { + cont.style.display = 'block'; + } else { + cont.style.display = 'none'; + } + } else { + var vis = cname.is(':visible'); + if (vis) { + cname.hide(); + } else { + cname.show(); + } + } + } + function removeWPUnload() { + window.onbeforeunload = null; + var w = jQuery(window); + w.off('beforeunload.widgets'); + w.off('beforeunload.edit-post'); + } + function addMultiselectLabelListener() { + var clickListener = function clickListener(e) { + if ('LABEL' !== e.target.nodeName) { + return; + } + var labelFor = e.target.getAttribute('for'); + if (!labelFor) { + return; + } + var input = document.getElementById(labelFor); + if (!input || !input.nextElementSibling) { + return; + } + var buttonToggle = input.nextElementSibling.querySelector('button.dropdown-toggle.multiselect'); + if (!buttonToggle) { + return; + } + var triggerMultiselectClick = function triggerMultiselectClick() { + return buttonToggle.click(); + }; + setTimeout(triggerMultiselectClick, 0); + }; + document.addEventListener('click', clickListener); + } + function maybeChangeEmbedFormMsg() { + var fieldId = jQuery(this).closest('.frm-single-settings').data('fid'); + var fieldItem = document.getElementById('frm_field_id_' + fieldId); + if (null === fieldItem || 'form' !== fieldItem.dataset.type) { + return; + } + fieldItem = jQuery(fieldItem); + if (this.options[this.selectedIndex].value) { + fieldItem.find('.frm-not-set')[0].classList.add('frm_hidden'); + var embedMsg = fieldItem.find('.frm-embed-message'); + embedMsg.html(embedMsg.data('embedmsg') + this.options[this.selectedIndex].text); + fieldItem.find('.frm-embed-field-placeholder')[0].classList.remove('frm_hidden'); + } else { + fieldItem.find('.frm-not-set')[0].classList.remove('frm_hidden'); + fieldItem.find('.frm-embed-field-placeholder')[0].classList.add('frm_hidden'); + } + } + function toggleProductType() { + var settings = jQuery(this).closest('.frm-single-settings'), + container = settings.find('.frmjs_product_choices'), + heading = settings.find('.frm_prod_options_heading'), + currentVal = this.options[this.selectedIndex].value; + container.removeClass('frm_prod_type_single frm_prod_type_user_def'); + heading.removeClass('frm_prod_user_def'); + if ('single' === currentVal) { + container.addClass('frm_prod_type_single'); + } else if ('user_def' === currentVal) { + container.addClass('frm_prod_type_user_def'); + heading.addClass('frm_prod_user_def'); + } + } + + /** + * @param {Number | string} fieldId + * @return {boolean} True if the field is a product field. + */ + function isProductField(fieldId) { + var field = document.getElementById('frm_field_id_' + fieldId); + if (field === null) { + return false; + } + return 'product' === field.getAttribute('data-type'); + } + + /** + * Serialize form data with vanilla JS. + */ + function formToData(form) { + var subKey, + i, + object = {}, + formData = form.elements; + for (i = 0; i < formData.length; i++) { + var input = formData[i], + key = input.name, + value = input.value, + names = key.match(/(.*)\[(.*)\]/); + if ((input.type === 'radio' || input.type === 'checkbox') && !input.checked) { + continue; + } + if (names !== null) { + key = names[1]; + subKey = names[2]; + if (!Reflect.has(object, key)) { + object[key] = {}; + } + object[key][subKey] = value; + continue; + } + + // Reflect.has in favor of: object.hasOwnProperty(key) + if (!Reflect.has(object, key)) { + object[key] = value; + continue; + } + if (!Array.isArray(object[key])) { + object[key] = [object[key]]; + } + object[key].push(value); + } + return object; + } + + /** + * Show, hide, and sort subfields of Name field on form builder. + * + * @since 4.11 + */ + function handleNameFieldOnFormBuilder() { + /** + * Gets subfield element from cache. + * + * @param {string} fieldId Field ID. + * @param {string} key Cache key. + * @return {HTMLElement|undefined} Return the element from cache or undefined if not found. + */ + var getSubFieldElFromCache = function getSubFieldElFromCache(fieldId, key) { + window.frmCachedSubFields = window.frmCachedSubFields || {}; + window.frmCachedSubFields[fieldId] = window.frmCachedSubFields[fieldId] || {}; + return window.frmCachedSubFields[fieldId][key]; + }; + + /** + * Sets subfield element to cache. + * + * @param {string} fieldId Field ID. + * @param {string} key Cache key. + * @param {HTMLElement} el Element. + */ + var setSubFieldElToCache = function setSubFieldElToCache(fieldId, key, el) { + window.frmCachedSubFields = window.frmCachedSubFields || {}; + window.frmCachedSubFields[fieldId] = window.frmCachedSubFields[fieldId] || {}; + window.frmCachedSubFields[fieldId][key] = el; + }; + + /** + * Gets column class from the number of columns. + * + * @param {Number} colCount Number of columns. + * @return {string} + */ + var getColClass = function getColClass(colCount) { + return 'frm' + parseInt(12 / colCount); + }; + var colClasses = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].map(function (num) { + return 'frm' + num; + }); + var allSubFieldNames = ['first', 'middle', 'last']; + + /** + * Handles name layout change. + * + * @param {Event} event Event object. + */ + var onChangeLayout = function onChangeLayout(event) { + var value = event.target.value; + var subFieldNames = value.split('_'); + var fieldId = event.target.dataset.fieldId; + + /* + * Live update form on the form builder. + */ + var container = document.querySelector('#field_' + fieldId + '_inner_container .frm_combo_inputs_container'); + var newColClass = getColClass(subFieldNames.length); + + // Set all sub field elements to cache and hide all of them first. + allSubFieldNames.forEach(function (name) { + var subFieldEl = container.querySelector('[data-sub-field-name="' + name + '"]'); + if (subFieldEl) { + var _subFieldEl$classList; + subFieldEl.classList.add('frm_hidden'); + (_subFieldEl$classList = subFieldEl.classList).remove.apply(_subFieldEl$classList, _toConsumableArray(colClasses)); + setSubFieldElToCache(fieldId, name, subFieldEl); + } + }); + subFieldNames.forEach(function (subFieldName) { + var subFieldEl = getSubFieldElFromCache(fieldId, subFieldName); + if (!subFieldEl) { + return; + } + subFieldEl.classList.remove('frm_hidden'); + subFieldEl.classList.add(newColClass); + container.append(subFieldEl); + }); + + /* + * Live update subfield options. + */ + // Hide all subfield options. + allSubFieldNames.forEach(function (name) { + var optionsEl = document.querySelector('.frm_sub_field_options-' + name + '[data-field-id="' + fieldId + '"]'); + if (optionsEl) { + optionsEl.classList.add('frm_hidden'); + setSubFieldElToCache(fieldId, name + '_options', optionsEl); + } + }); + subFieldNames.forEach(function (subFieldName) { + var optionsEl = getSubFieldElFromCache(fieldId, subFieldName + '_options'); + if (!optionsEl) { + return; + } + optionsEl.classList.remove('frm_hidden'); + }); + }; + var dropdownSelector = '.frm_name_layout_dropdown'; + document.addEventListener('change', function (event) { + if (event.target.matches(dropdownSelector)) { + onChangeLayout(event); + } + }, false); + } + function debounce(func) { + var wait = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; + return frmDom.util.debounce(func, wait); + } + function addSaveAndDragIconsToOption(fieldId, liObject) { + var li, useTag, useTagHref; + var hasDragIcon = false; + var hasSaveIcon = false; + if (liObject.newOption) { + var parser = new DOMParser(); + li = parser.parseFromString(liObject.newOption, 'text/html').body.childNodes[0]; + } else { + li = liObject; + } + var liIcons = li.querySelectorAll('svg'); + liIcons.forEach(function (svg, key) { + useTag = svg.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'use')[0]; + if (!useTag) { + return; + } + useTagHref = useTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || useTag.getAttribute('href'); + if (useTagHref === '#frm_drag_icon') { + hasDragIcon = true; + } + if (useTagHref === '#frm_save_icon') { + hasSaveIcon = true; + } + }); + if (!hasDragIcon) { + li.prepend(icons.drag.cloneNode(true)); + } + if (li.querySelector("[id^=field_key_".concat(fieldId, "-]")) && !hasSaveIcon) { + li.querySelector("[id^=field_key_".concat(fieldId, "-]")).after(icons.save.cloneNode(true)); + } + if (liObject.newOption) { + liObject.newOption = li; + } + } + function maybeAddSaveAndDragIcons(fieldId) { + var fieldOptions = document.querySelectorAll("[id^=frm_delete_field_".concat(fieldId, "-]")); + // return if there are no options. + if (fieldOptions.length < 2) { + return; + } + var options = _toConsumableArray(fieldOptions).slice(1); + options.forEach(function (li, _key) { + if (li.classList.contains('frm_other_option')) { + return; + } + addSaveAndDragIconsToOption(fieldId, li); + }); + } + + /** + * Enforce the maximum number of entries list columns dynamically. + * + * @since 6.24 + * + * @return {void} + */ + function maybeInitEntriesListPage() { + if (!document.body.classList.contains('frm-admin-page-entries')) { + return; + } + var screenOptionsWrapper = document.getElementById('screen-options-wrap'); + if (!screenOptionsWrapper) { + return; + } + var maxSelectionsNote = div({ + className: 'frm_warning_style', + text: __('Only 10 columns can be selected at a time.', 'formidable') + }); + maxSelectionsNote.style.margin = 0; + var legend = screenOptionsWrapper.querySelector('legend'); + legend.parentNode.insertBefore(maxSelectionsNote, legend.nextElementSibling); + var checkboxes = Array.from(screenOptionsWrapper.querySelectorAll('input[type="checkbox"]')); + var maximumColumns = 10; + var getSelectedCount = function getSelectedCount() { + return checkboxes.reduce(function (count, checkbox) { + return checkbox.checked ? count + 1 : count; + }, 0); + }; + var disableCheckboxesIfAtMax = function disableCheckboxesIfAtMax() { + if (getSelectedCount() >= maximumColumns) { + maxSelectionsNote.classList.remove('frm_hidden'); + checkboxes.forEach(function (checkbox) { + if (!checkbox.checked) { + checkbox.parentNode.classList.add('frm_noallow'); + checkbox.disabled = true; + } + }); + } else { + maxSelectionsNote.classList.add('frm_hidden'); + } + }; + var addCheckboxListeners = function addCheckboxListeners() { + checkboxes.forEach(function (checkbox) { + checkbox.addEventListener('change', function (event) { + if (event.target.checked) { + disableCheckboxesIfAtMax(); + } else { + maxSelectionsNote.classList.add('frm_hidden'); + + // Enable all checkboxes when a checkbox is unchecked. + checkboxes.forEach(function (checkbox) { + checkbox.parentNode.classList.remove('frm_noallow'); + checkbox.disabled = false; + }); + } + }); + }); + }; + disableCheckboxesIfAtMax(); + addCheckboxListeners(); + } + function initOnSubmitAction() { + var onChangeType = function onChangeType(event) { + if (!event.target.checked) { + return; + } + var actionEl = event.target.closest('.frm_form_action_settings'); + actionEl.querySelectorAll('.frm_on_submit_dependent_setting:not(.frm_hidden)').forEach(function (el) { + el.classList.add('frm_hidden'); + }); + var activeEls = actionEl.querySelectorAll('.frm_on_submit_dependent_setting[data-show-if-' + event.target.value + ']'); + activeEls.forEach(function (activeEl) { + activeEl.classList.remove('frm_hidden'); + }); + actionEl.setAttribute('data-on-submit-type', event.target.value); + }; + frmDom.util.documentOn('change', '.frm_on_submit_type input[type="radio"]', onChangeType); + } + + /** + * Listen for click events for an API-loaded email collection form. + * + * This is used for the Active Campaign sign-up form in the inbox page (when there are no messages). + */ + function initAddMyEmailAddress() { + jQuery(document).on('click', '#frm-add-my-email-address', function (event) { + event.preventDefault(); + addMyEmailAddress(); + }); + var emptyInbox = document.getElementById('frm_empty_inbox'); + var leaveEmailInput = document.getElementById('frm_leave_email'); + if (emptyInbox && leaveEmailInput) { + var leaveEmailModal = document.getElementById('frm-leave-email-modal'); + leaveEmailModal.classList.remove('frm_hidden'); + leaveEmailModal.querySelector('.frm_modal_footer').classList.add('frm_hidden'); + leaveEmailInput.addEventListener('keyup', function (event) { + if ('Enter' === event.key) { + var button = document.getElementById('frm-add-my-email-address'); + if (button) { + button.click(); + } + } + }); + } + } + function addMyEmailAddress() { + var email = document.getElementById('frm_leave_email').value.trim(); + if ('' === email) { + handleEmailAddressError('empty'); + return; + } + var regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i; + if (regex.test(email) === false) { + handleEmailAddressError('invalid'); + return; + } + var $hiddenForm = jQuery('#frmapi-email-form').find('form'); + var $hiddenEmailField = $hiddenForm.find('[type="email"]').not('.frm_verify'); + if (!$hiddenEmailField.length) { + return; + } + var emptyInbox = document.getElementById('frm_empty_inbox'); + if (emptyInbox) { + document.getElementById('frm-add-my-email-address').remove(); + var emailWrapper = document.getElementById('frm_leave_email_wrapper'); + if (emailWrapper) { + emailWrapper.classList.add('frm_hidden'); + var spinner = span({ + className: 'frm-wait frm_spinner' + }); + spinner.style.visibility = 'visible'; + spinner.style.float = 'none'; + spinner.style.width = 'unset'; + emailWrapper.parentElement.insertBefore(spinner, emailWrapper.nextElementSibling); + } + } + $hiddenEmailField.val(email); + jQuery.ajax({ + type: 'POST', + url: $hiddenForm.attr('action'), + data: $hiddenForm.serialize() + '&action=frm_forms_preview' + }).done(function (data) { + var message = jQuery(data).find('.frm_message').text().trim(); + if (message.indexOf('Thanks!') === -1) { + handleEmailAddressError('invalid'); + return; + } + var apiForm = document.getElementById('frmapi-email-form'); + var spinner = apiForm.parentElement.querySelector('.frm_spinner'); + if (spinner) { + spinner.remove(); + } + var showSuccessMessage = wp.hooks.applyFilters('frm_thank_you_on_signup', true); + if (showSuccessMessage) { + // Handle successful form submission. + // handle the Active Campaign form on the inbox page. + document.getElementById('frm_leave_email_wrapper').replaceWith(span(__('Thank you for signing up!', 'formidable'))); + } + }); + } + + /** + * Adds footer links to the admin body content. + * + * @return {void} + */ + function addAdminFooterLinks() { + var _document$querySelect7; + var footerLinks = document.querySelector('.frm-admin-footer-links'); + var container = (_document$querySelect7 = document.querySelector('.frm_page_container')) !== null && _document$querySelect7 !== void 0 ? _document$querySelect7 : document.getElementById('wpbody-content'); + if (!footerLinks || !container) { + return; + } + container.appendChild(footerLinks); + footerLinks.classList.remove('frm_hidden'); + } + + /** + * Apply zebra striping to a table while ignoring empty rows. + * + * @param {string} tableSelector The CSS selector for the table. + * @param {string} emptyRowClass The class name used to identify empty rows. + */ + function applyZebraStriping(tableSelector, emptyRowClass) { + // Get all non-empty table rows within the specified table + var rows = document.querySelectorAll("".concat(tableSelector, " tr").concat(emptyRowClass ? ":not(.".concat(emptyRowClass, ")") : '')); + if (rows.length < 1) { + return; + } + var isOdd = true; + rows.forEach(function (row) { + // Clean old "frm-odd" or "frm-even" classes and add the appropriate new class + row.classList.remove('frm-odd', 'frm-even'); + row.classList.add(isOdd ? 'frm-odd' : 'frm-even'); + isOdd = !isOdd; + }); + var tables = document.querySelectorAll(tableSelector); + tables.forEach(function (table) { + return table.classList.add('frm-zebra-striping'); + }); + } + function maybeHideShortcodes(e) { + if (!builderPage) { + e.stopPropagation(); + } + if (e.target.classList.contains('frm-show-box') || e.target.parentElement && e.target.parentElement.classList.contains('frm-show-box')) { + return; + } + var sidebar = document.getElementById('frm_adv_info'); + if (!sidebar) { + return; + } + if (sidebar.dataset.fills === e.target.id && typeof e.target.id !== 'undefined') { + return; + } + var isChild = e.target.closest('#frm_adv_info'); + if (!isChild && sidebar.style.display !== 'none') { + hideShortcodes(sidebar); + } + } + + /** + * Initializes and manages the visibility of dependent elements based on the selected options in dropdowns with the 'frm_select_with_dependency' class. + * It sets up initial visibility at page load and updates it on each dropdown change. + * + * @since 6.9 + * + * @return {void} + */ + function initSelectDependencies() { + var selects = document.querySelectorAll('select.frm_select_with_dependency'); + + /** + * Toggles the visibility of dependent elements associated with a select element based on its current selection. + * + * @since 6.9 + * + * @param {HTMLElement} select The select element whose dependencies need to be managed. + * @return {void} + */ + function toggleDependencyVisibility(select) { + var selectedOption = select.options[select.selectedIndex]; + select.querySelectorAll('option[data-dependency]:not([data-dependency-skip])').forEach(function (option) { + var dependencyElement = document.querySelector(option.dataset.dependency); + dependencyElement === null || dependencyElement === void 0 || dependencyElement.classList.toggle('frm_hidden', selectedOption !== option); + }); + } + + // Initial setup: Show dependencies based on the current selection in each dropdown + selects.forEach(toggleDependencyVisibility); + + // Update dependencies visibility on dropdown change + frmDom.util.documentOn('change', 'select.frm_select_with_dependency', function (event) { + return toggleDependencyVisibility(event.target); + }); + } + + /** + * Moves the focus to the next single option input field in the list and positions the cursor at the end of the text. + * + * @param {HTMLElement} currentInput The currently focused input element. + */ + function focusNextSingleOptionInput(currentInput) { + var optionsList = currentInput.closest('.frm_single_option').parentElement; + var inputs = optionsList.querySelectorAll('.frm_single_option input[name^="field_options[" ], .frm_single_option input[name^="rows_"]'); + var inputsArray = Array.from(inputs); + + // Find the index of the currently focused input + var currentIndex = inputsArray.indexOf(currentInput); + if (currentIndex < 0) { + return; + } + + // Find the next visible input field + var nextInput = inputsArray.slice(currentIndex + 1).find(function (input) { + return input.offsetParent !== null; + }); + if (nextInput) { + nextInput.focus(); + + // Move the cursor to the end of the text in the next input field + var textLength = nextInput.value.length; + nextInput.setSelectionRange(textLength, textLength); + } + } + return { + init: function init() { + initAddMyEmailAddress(); + addAdminFooterLinks(); + s = {}; + + // Bootstrap dropdown button + jQuery('.wp-admin').on('click', function (e) { + var t = jQuery(e.target); + var $openDrop = jQuery('.dropdown.open'); + if ($openDrop.length && !t.hasClass('dropdown') && !t.closest('.dropdown').length) { + $openDrop.removeClass('open'); + } + }); + jQuery('#frm_bs_dropdown:not(.open) a').on('click', focusSearchBox); + if (typeof thisFormId === 'undefined') { + thisFormId = jQuery(document.getElementById('form_id')).val(); + } + + // Add event listener for dismissible warning messages. + document.querySelectorAll('.frm-warning-dismiss').forEach(function (dismissIcon) { + onClickPreventDefault(dismissIcon, dismissWarningMessage); + }); + frmAdminBuild.inboxBannerInit(); + if ($newFields.length > 0) { + // only load this on the form builder page + frmAdminBuild.buildInit(); + } else if (document.getElementById('frm_notification_settings') !== null) { + // only load on form settings page + frmAdminBuild.settingsInit(); + } else if (document.getElementById('frm_styling_form') !== null) { + // load styling settings js + frmAdminBuild.styleInit(); + } else if (document.getElementById('form_global_settings') !== null) { + // global settings page + frmAdminBuild.globalSettingsInit(); + } else if (document.getElementById('frm_export_xml') !== null) { + // import/export page + frmAdminBuild.exportInit(); + } else if (null !== document.querySelector('.frm-inbox-wrapper')) { + // Dashboard page inbox. + frmAdminBuild.inboxInit(); + } else if (document.getElementById('frm-welcome') !== null) { + // Solution install page + frmAdminBuild.solutionInit(); + } else { + maybeInitEntriesListPage(); + initAutocomplete(); + jQuery('[data-frmprint]').on('click', function () { + window.print(); + return false; + }); + } + jQuery(document).on('change', 'select[data-toggleclass], input[data-toggleclass]', toggleFormOpts); + initSelectDependencies(); + var $advInfo = jQuery(document.getElementById('frm_adv_info')); + if ($advInfo.length > 0 || jQuery('.frm_field_list').length > 0) { + // only load on the form, form settings, and view settings pages + frmAdminBuild.panelInit(); + } + loadTooltips(); + initUpgradeModal(); + frmDom.util.documentOn('click', '[data-modal-title]', showBasicModal); + + // used on build, form settings, and view settings + var $shortCodeDiv = jQuery(document.getElementById('frm_shortcodediv')); + if ($shortCodeDiv.length > 0) { + jQuery('a.edit-frm_shortcode').on('click', function () { + if ($shortCodeDiv.is(':hidden')) { + $shortCodeDiv.slideDown('fast'); + this.style.display = 'none'; + } + return false; + }); + jQuery('.cancel-frm_shortcode', '#frm_shortcodediv').on('click', function () { + $shortCodeDiv.slideUp('fast'); + $shortCodeDiv.siblings('a.edit-frm_shortcode').show(); + return false; + }); + } + + // tabs + jQuery(document).on('click', '#frm-nav-tabs a', clickNewTab); + jQuery('.post-type-frm_display .frm-nav-tabs a, .frm-category-tabs a').on('click', function () { + var showUpgradeTab = this.classList.contains('frm_show_upgrade_tab'); + if (this.classList.contains('frm_noallow') && !showUpgradeTab) { + return; + } + if (showUpgradeTab) { + populateUpgradeTab(this); + } + clickTab(this); + return false; + }); + clickTab(jQuery('.starttab a'), 'auto'); + + // submit the search form with dropdown + jQuery(document).on('click', '#frm-fid-search-menu a', function () { + var val = this.id.replace('fid-', ''); + jQuery('select[name="fid"]').val(val); + triggerSubmit(document.getElementById('posts-filter')); + return false; + }); + jQuery('.frm_select_box').on('click focus', function () { + this.select(); + }); + jQuery(document).on('input search change', '.frm-auto-search:not(#frm-form-templates-page #template-search-input)', searchContent); + jQuery(document).on('focusin click', '.frm-auto-search', stopPropagation); + var autoSearch = jQuery('.frm-auto-search'); + if (autoSearch.val() !== '') { + autoSearch.trigger('keyup'); + } + + // Initialize Formidable Connection. + FrmFormsConnect.init(); + jQuery(document).on('click', '.frm-install-addon', installAddon); + jQuery(document).on('click', '.frm-activate-addon', activateAddon); + jQuery(document).on('click', '.frm-solution-multiple', installMultipleAddons); + + // prevent annoying confirmation message from WordPress + jQuery('button, input[type=submit]').on('click', removeWPUnload); + addMultiselectLabelListener(); + frmAdminBuild.hooks.addFilter('frm_before_embed_modal', function (ids, _ref4) { + var element = _ref4.element, + type = _ref4.type; + if ('form' !== type) { + return ids; + } + var formId, formKey; + var row = element.closest('tr'); + if (row) { + // Embed icon on form index. + formId = parseInt(row.querySelector('.column-id').textContent); + formKey = row.querySelector('.column-form_key').textContent; + } else { + // Embed button in form builder / form settings. + formId = document.getElementById('form_id').value; + var formKeyInput = document.getElementById('frm_form_key'); + if (formKeyInput) { + formKey = formKeyInput.value; + } else { + var previewDrop = document.getElementById('frm-previewDrop'); + if (previewDrop) { + formKey = previewDrop.nextElementSibling.querySelector('.dropdown-item a').getAttribute('href').split('form=')[1]; + } + } + } + return [formId, formKey]; + }); + document.querySelectorAll('#frm-show-fields > li, .frm_grid_container li').forEach(function (el, _key) { + el.addEventListener('click', function () { + var _this$querySelector; + var fieldId = ((_this$querySelector = this.querySelector('li')) === null || _this$querySelector === void 0 ? void 0 : _this$querySelector.dataset.fid) || this.dataset.fid; + maybeAddSaveAndDragIcons(fieldId); + }); + }); + var smallScreenProceedButton = document.getElementById('frm_small_screen_proceed_button'); + if (smallScreenProceedButton) { + onClickPreventDefault(smallScreenProceedButton, function () { + var _document$getElementB5; + (_document$getElementB5 = document.getElementById('frm_small_device_message_container')) === null || _document$getElementB5 === void 0 || _document$getElementB5.remove(); + doJsonPost('small_screen_proceed', new FormData()); + }); + } + var saleBanner = document.getElementById('frm_sale_banner'); + var saleDismiss = saleBanner === null || saleBanner === void 0 ? void 0 : saleBanner.querySelector('.dismiss'); + if (saleBanner) { + onClickPreventDefault(saleBanner, function (event) { + var target = event.target; + if (target.closest('.dismiss')) { + return; + } + window.location.href = saleBanner.getAttribute('data-url'); + }); + if (saleDismiss) { + onClickPreventDefault(saleDismiss, function () { + saleBanner.remove(); + var formData = new FormData(); + doJsonPost('sale_banner_dismiss', formData); + }); + } + } + }, + buildInit: function buildInit() { + jQuery('#frm_builder_page').on('mouseup', '*:not(.frm-show-box)', maybeHideShortcodes); + var loadFieldId, $builderForm, builderArea; + debouncedSyncAfterDragAndDrop = debounce(syncAfterDragAndDrop, 10); + postBodyContent = document.getElementById('post-body-content'); + $postBodyContent = jQuery(postBodyContent); + if (jQuery('.frm_field_loading').length) { + loadFieldId = jQuery('.frm_field_loading').first().attr('id'); + loadFields(loadFieldId); + } + setupSortable('ul.frm_sorting'); + document.querySelectorAll('.field_type_list > li:not(.frm_show_upgrade)').forEach(makeDraggable); + jQuery('ul.field_type_list, .field_type_list li, ul.frm_code_list, .frm_code_list li, .frm_code_list li a, #frm_adv_info #category-tabs li, #frm_adv_info #category-tabs li a').disableSelection(); + jQuery('.frm_submit_ajax').on('click', submitBuild); + jQuery('.frm_submit_no_ajax').on('click', submitNoAjax); + addFormNameModalEvents(); + jQuery('a.edit-form-status').on('click', slideDown); + jQuery('.cancel-form-status').on('click', slideUp); + jQuery('.save-form-status').on('click', function () { + var newStatus = jQuery(document.getElementById('form_change_status')).val(); + jQuery('input[name="new_status"]').val(newStatus); + jQuery(document.getElementById('form-status-display')).html(newStatus); + jQuery('.cancel-form-status').trigger('click'); + return false; + }); + jQuery('.frm_form_builder form').first().on('submit', function () { + jQuery('.inplace_field').trigger('blur'); + }); + initiateMultiselect(); + renumberPageBreaks(); + $builderForm = jQuery(builderForm); + builderArea = document.getElementById('frm_form_editor_container'); + $builderForm.on('click', '.frm_add_logic_row', addFieldLogicRow); + $builderForm.on('click', '.frm_add_watch_lookup_row', addWatchLookupRow); + $builderForm.on('change', '.frm_get_values_form', updateGetValueFieldSelection); + $builderForm.on('change', '.frm_logic_field_opts', getFieldValues); + $builderForm.on('frm-multiselect-changed', 'select[name^="field_options[admin_only_"]', adjustVisibilityValuesForEveryoneValues); + jQuery(document.getElementById('frm-insert-fields')).on('click', '.frm_add_field', addFieldClick); + $newFields.on('click', '.frm_clone_field', duplicateField); + $builderForm.on('blur', 'input[id^="frm_calc"]', checkCalculationCreatedByUser); + $builderForm.on('change', 'input.frm_format_opt, input.frm_max_length_opt', toggleInvalidMsg); + $builderForm.on('change click', '[data-changeme]', liveChanges); + $builderForm.on('click', 'input.frm_req_field', markRequired); + $builderForm.on('click', '.frm_mark_unique', markUnique); + $builderForm.on('change', '.frm_repeat_format', toggleRepeatButtons); + $builderForm.on('change', '.frm_repeat_limit', checkRepeatLimit); + $builderForm.on('change', '.frm_js_checkbox_limit', checkCheckboxSelectionsLimit); + $builderForm.on('input', 'input[name^="field_options[add_label_"]', function () { + updateRepeatText(this, 'add'); + }); + $builderForm.on('input', 'input[name^="field_options[remove_label_"]', function () { + updateRepeatText(this, 'remove'); + }); + $builderForm.on('change', 'select[name^="field_options[data_type_"]', maybeClearWatchFields); + jQuery(builderArea).on('click', '.frm-collapse-page', maybeCollapsePage); + jQuery(builderArea).on('click', '.frm-collapse-section', maybeCollapseSection); + $builderForm.on('click', '.frm-single-settings h3, .frm-single-settings h4.frm-collapsible', maybeCollapseSettings); + $builderForm.on('keydown', '.frm-single-settings h3, .frm-single-settings h4.frm-collapsible', function (event) { + // If so, only proceed if the key pressed was 'Enter' or 'Space' + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + maybeCollapseSettings.call(this, event); + } + }); + jQuery(builderArea).on('show.bs.dropdown hide.bs.dropdown', changeSectionStyle); + $builderForm.on('click', '.frm_toggle_sep_values', toggleSepValues); + $builderForm.on('click', '.frm_toggle_image_options', toggleImageOptions); + $builderForm.on('click', '.frm_remove_image_option', removeImageFromOption); + $builderForm.on('click', '.frm_choose_image_box', addImageToOption); + $builderForm.on('change', '.frm_hide_image_text', refreshOptionDisplay); + $builderForm.on('change', '.frm_field_options_image_size', setImageSize); + $builderForm.on('click', '.frm_multiselect_opt', toggleMultiselect); + $newFields.on('mousedown', 'input, textarea, select', stopFieldFocus); + $newFields.on('click', 'input[type=radio], input[type=checkbox]', stopFieldFocus); + $newFields.on('click', '.frm_delete_field', clickDeleteField); + $newFields.on('click', '.frm_select_field', clickSelectField); + jQuery(document).on('click', '.frm_delete_field_group', clickDeleteFieldGroup); + jQuery(document).on('click', '.frm_clone_field_group', duplicateFieldGroup); + jQuery(document).on('click', '#frm_field_group_controls > span:first-child', clickFieldGroupLayout); + jQuery(document).on('click', '.frm-row-layout-option', handleFieldGroupLayoutOptionClick); + jQuery(document).on('click', '.frm-merge-fields-into-row .frm-row-layout-option', handleFieldGroupLayoutOptionInsideMergeClick); + jQuery(document).on('click', '.frm-custom-field-group-layout', customFieldGroupLayoutClick); + jQuery(document).on('click', '.frm-merge-fields-into-row .frm-custom-field-group-layout', customFieldGroupLayoutInsideMergeClick); + jQuery(document).on('click', '.frm-break-field-group', breakFieldGroupClick); + $newFields.on('click', '#frm_field_group_popup .frm_grid_container input', focusFieldGroupInputOnClick); + jQuery(document).on('click', '.frm-cancel-custom-field-group-layout', cancelCustomFieldGroupClick); + jQuery(document).on('click', '.frm-save-custom-field-group-layout', saveCustomFieldGroupClick); + $newFields.on('click', 'ul.frm_sorting', fieldGroupClick); + jQuery(document).on('click', '.frm-merge-fields-into-row', mergeFieldsIntoRowClick); + jQuery(document).on('click', '.frm-delete-field-groups', deleteFieldGroupsClick); + $newFields.on('click', '.frm-field-action-icons [data-toggle="dropdown"]', function () { + this.closest('li.form-field').classList.add('frm-field-settings-open'); + jQuery(document).on('click', '#frm_builder_page', handleClickOutsideOfFieldSettings); + }); + $newFields.on('mousemove', 'ul.frm_sorting', checkForMultiselectKeysOnMouseMove); + $newFields.on('show.bs.dropdown', '.frm-field-action-icons', onFieldActionDropdownShow); + jQuery(document).on('show.bs.dropdown', '#frm_field_group_controls', onFieldGroupActionDropdownShow); + $builderForm.on('click', '.frm_single_option a[data-removeid]', deleteFieldOption); + $builderForm.on('mousedown', '.frm_single_option input[type=radio]', maybeUncheckRadio); + $builderForm.on('focusin', '.frm_single_option input[type=text]', maybeClearOptText); + $builderForm.on('click', '.frm_add_opt', addFieldOption); + $builderForm.on('change', '.frm_single_option input', resetOptOnChange); + $builderForm.on('change', '.frm_image_id', resetOptOnChange); + $builderForm.on('change', '.frm_toggle_mult_sel', toggleMultSel); + $newFields.on('click', '.frm_primary_label', clickLabel); + $newFields.on('click', '.frm_description', clickDescription); + $newFields.on('click', 'li.ui-state-default:not(.frm_noallow)', clickVis); + $newFields.on('dblclick', 'li.ui-state-default', openAdvanced); + $builderForm.on('change', '.frm_tax_form_select', toggleFormTax); + $builderForm.on('change', 'select.conf_field', addConf); + $builderForm.on('change', '.frm_get_field_selection', getFieldSelection); + $builderForm.on('click', '.frm-show-inline-modal', maybeShowInlineModal); + $builderForm.on('keydown', '.frm-show-inline-modal', function (event) { + var key = event.key; + if (key === 'Enter' || key === ' ') { + event.preventDefault(); + maybeShowInlineModal.call(this, event); + } + }); + $builderForm.on('click', '.frm-inline-modal .dismiss', dismissInlineModal); + jQuery(document).on('change', '[data-frmchange]', changeInputtedValue); + document.addEventListener('click', closeModalOnOutsideClick); + $builderForm.on('change', '.frm_include_extras_field', rePopCalcFieldsForSummary); + $builderForm.on('change', 'select[name^="field_options[form_select_"]', maybeChangeEmbedFormMsg); + jQuery(document).on('submit', '#frm_js_build_form', buildSubmittedNoAjax); + jQuery(document).on('change', '#frm_builder_page input:not(.frm-search-input):not(.frm-custom-grid-size-input), #frm_builder_page select, #frm_builder_page textarea', fieldUpdated); + popAllProductFields(); + jQuery(document).on('change', '.frmjs_prod_data_type_opt', toggleProductType); + jQuery(document).on('focus', '.frm-single-settings ul input[type="text"][name^="field_options[options_"]', onOptionTextFocus); + jQuery(document).on('blur', '.frm-single-settings ul input[type="text"][name^="field_options[options_"]', onOptionTextBlur); + frmDom.util.documentOn('click', '.frm-show-field-settings', clickVis); + frmDom.util.documentOn('change', 'select.frm_format_dropdown, select.frm_phone_type_dropdown', maybeUpdateFormatInput); + + // Navigate to the next input field on pressing Enter in a single option field + $builderForm.on('keydown', '.frm_single_option input[name^="field_options["], .frm_single_option input[name^="rows_"]', function (event) { + if ('Enter' === event.key) { + focusNextSingleOptionInput(event.currentTarget); + } + }); + initBulkOptionsOverlay(); + hideEmptyEle(); + document.addEventListener('frm_added_field', hideEmptyEle); + maybeHideQuantityProductFieldOption(); + handleNameFieldOnFormBuilder(); + toggleSectionHolder(); + handleShowPasswordLiveUpdate(); + document.addEventListener('scroll', updateShortcodesPopupPosition, true); + document.addEventListener('change', handleBuilderChangeEvent); + document.querySelector('.frm_form_builder').addEventListener('mousedown', function (event) { + if (event.shiftKey) { + event.preventDefault(); + } + }); + wp.hooks.addAction('frmShowedFieldSettings', 'formidableAdmin', function (showBtn, fieldSettingsEl) { + fieldSettingsEl.querySelectorAll('.frm-collapse-me').forEach(addSlideAnimationCssVars); + }, 9999); + }, + settingsInit: function settingsInit() { + var $formActions = jQuery(document.getElementById('frm_notification_settings')); + var formSettings, $loggedIn, $cookieExp, $editable; + + // BCC, CC, and Reply To button functionality + $formActions.on('click', '.frm_email_buttons', showEmailRow); + $formActions.on('click', '.frm_remove_field', hideEmailRow); + $formActions.on('change', '.frm_to_row, .frm_from_row', showEmailWarning); + $formActions.on('change', '.frm_tax_selector', changePosttaxRow); + $formActions.on('change', 'select.frm_single_post_field', checkDupPost); + $formActions.on('change', 'select.frm_toggle_post_content', togglePostContent); + $formActions.on('change', 'select.frm_dyncontent_opt', fillDyncontent); + $formActions.on('change', '.frm_post_type', switchPostType); + $formActions.on('click', '.frm_add_postmeta_row', addPostmetaRow); + $formActions.on('click', '.frm_add_posttax_row', addPosttaxRow); + $formActions.on('click', '.frm_toggle_cf_opts', toggleCfOpts); + $formActions.on('click', '.frm_duplicate_form_action', copyFormAction); + jQuery('.frm_actions_list').on('click', '.frm_active_action', addFormAction); + jQuery('#frm-show-groups, #frm-hide-groups').on('click', toggleActionGroups); + initiateMultiselect(); + + //set actions icons to inactive + jQuery('ul.frm_actions_list li').each(function () { + checkActiveAction(jQuery(this).children('a').data('actiontype')); + + // If the icon is a background image, don't add BG color. + var icon = jQuery(this).find('i'); + if (icon.css('background-image') !== 'none') { + icon.addClass('frm-inverse'); + } + }); + jQuery('.frm_submit_settings_btn').on('click', submitSettings); + addFormNameModalEvents(); + formSettings = jQuery('.frm_form_settings'); + formSettings.on('click', '.frm_add_form_logic', addFormLogicRow); + formSettings.on('click', '.frm_already_used', actionLimitMessage); + document.addEventListener('click', function handleImageUploadClickEvents(event) { + var target = event.target; + if (!target.closest('.frm_image_preview_wrapper')) { + return; + } + if (target.closest('.frm_choose_image_box')) { + addImageToOption.bind(target)(event); + return; + } + if (target.closest('.frm_remove_image_option')) { + removeImageFromOption.bind(target)(event); + } + }); + + // Close shortcode modal on click. + formSettings.on('mouseup', '*:not(.frm-show-box)', maybeHideShortcodes); + + //Warning when user selects "Do not store entries ..." + jQuery(document.getElementById('no_save')).on('change', function () { + if (this.checked) { + if (confirm(frmAdminJs.no_save_warning) !== true) { + // Uncheck box if user hits "Cancel" + jQuery(this).attr('checked', false); + } + } + }); + jQuery('select[name="options[edit_action]"]').on('change', showSuccessOpt); + $loggedIn = document.getElementById('logged_in'); + jQuery($loggedIn).on('change', function () { + if (this.checked) { + visible('.hide_logged_in'); + } else { + invisible('.hide_logged_in'); + } + }); + $cookieExp = jQuery(document.getElementById('frm_cookie_expiration')); + jQuery(document.getElementById('frm_single_entry_type')).on('change', function () { + if (this.value === 'cookie') { + $cookieExp.fadeIn('slow'); + } else { + $cookieExp.fadeOut('slow'); + } + }); + var $singleEntry = document.getElementById('single_entry'); + jQuery($singleEntry).on('change', function () { + if (this.checked) { + visible('.hide_single_entry'); + } else { + invisible('.hide_single_entry'); + } + if (this.checked && jQuery(document.getElementById('frm_single_entry_type')).val() === 'cookie') { + $cookieExp.fadeIn('slow'); + } else { + $cookieExp.fadeOut('slow'); + } + }); + jQuery('.hide_save_draft').hide(); + var $saveDraft = jQuery(document.getElementById('save_draft')); + $saveDraft.on('change', function () { + if (this.checked) { + jQuery('.hide_save_draft').fadeIn('slow'); + } else { + jQuery('.hide_save_draft').fadeOut('slow'); + } + }); + triggerChange($saveDraft); + + //If Allow editing is checked/unchecked + $editable = document.getElementById('editable'); + jQuery($editable).on('change', function () { + if (this.checked) { + jQuery('.hide_editable').fadeIn('slow'); + triggerChange(document.getElementById('edit_action')); + } else { + jQuery('.hide_editable').fadeOut('slow'); + jQuery('.edit_action_message_box').fadeOut('slow'); //Hide On Update message box + } + }); + + //If File Protection is checked/unchecked + jQuery(document).on('change', '#protect_files', function () { + if (this.checked) { + jQuery('.hide_protect_files').fadeIn('slow'); + } else { + jQuery('.hide_protect_files').fadeOut('slow'); + } + }); + jQuery(document).on('frm-multiselect-changed', '#protect_files_role', adjustVisibilityValuesForEveryoneValues); + jQuery(document).on('submit', '.frm_form_settings', settingsSubmitted); + jQuery(document).on('change', '#form_settings_page input:not(.frm-search-input), #form_settings_page select, #form_settings_page textarea', fieldUpdated); + + // Page Selection Autocomplete + initAutocomplete(); + jQuery(document).on('frm-action-loaded', onActionLoaded); + initOnSubmitAction(); + wp.hooks.addAction('frm_reset_fields_updated', 'formidableAdmin', resetFieldsUpdated); + }, + panelInit: function panelInit() { + var customPanel, settingsPage, viewPage, insertFieldsTab; + jQuery('.frm_wrap, #postbox-container-1').on('click', '.frm_insert_code', insertCode); + jQuery(document).on('change', '.frm_insert_val', function () { + insertFieldCode(jQuery(this).data('target'), jQuery(this).val()); + jQuery(this).val(''); + }); + jQuery(document).on('click change', '[name="frm-id-key-condition"]', resetLogicBuilder); + jQuery(document).on('keyup change', '.frm-build-logic', setLogicExample); + showInputIcon(); + jQuery(document).on('frmElementAdded', function (event, parentEle) { + /* This is here for add-ons to trigger */ + showInputIcon(parentEle); + }); + jQuery(document).on('mousedown', '.frm-show-box', showShortcodes); + settingsPage = document.getElementById('form_settings_page'); + viewPage = document.body.classList.contains('post-type-frm_display'); + insertFieldsTab = document.getElementById('frm_insert_fields_tab'); + if (settingsPage !== null || viewPage || builderPage) { + jQuery(document).on('focusin', 'form input, form textarea', function (e) { + var htmlTab; + e.stopPropagation(); + maybeShowModal(this); + if (jQuery(this).is(':not(:submit, input[type=button], .frm-search-input, input[type=checkbox])')) { + if (jQuery(e.target).closest('#frm_adv_info').length) { + // Don't trigger for fields inside of the modal. + return; + } + if (settingsPage !== null || builderPage) { + /* form settings page */ + htmlTab = jQuery('#frm_html_tab'); + if (jQuery(this).closest('#html_settings').length > 0) { + htmlTab.show(); + htmlTab.siblings().hide(); + jQuery('#frm_html_tab a').trigger('click'); + toggleAllowedHTML(this); + } else { + showElement(jQuery('.frm-category-tabs li')); + insertFieldsTab.click(); + htmlTab.hide(); + htmlTab.siblings().show(); + } + } else if (viewPage) { + var event = new CustomEvent('frm_legacy_views_handle_field_focus'); + event.frmData = { + idAttrValue: this.id + }; + document.dispatchEvent(event); + } + } + }); + } + jQuery('.frm_wrap, #postbox-container-1').on('mousedown', '#frm_adv_info a, .frm_field_list a', function (e) { + e.preventDefault(); + }); + customPanel = jQuery('#frm_adv_info'); + customPanel.on('click', '.subsubsub a.frmids', function (e) { + toggleKeyID('frmids', e); + }); + customPanel.on('click', '.subsubsub a.frmkeys', function (e) { + toggleKeyID('frmkeys', e); + }); + }, + inboxInit: function inboxInit() { + var _document$getElementB6; + jQuery('.frm_inbox_dismiss').on('click', function (e) { + var message = this.parentNode.parentNode; + var key = message.getAttribute('data-message'); + var href = this.getAttribute('href'); + var dismissedMessage = message.cloneNode(true); + var dismissedMessagesWrapper = document.querySelector('.frm-dismissed-inbox-messages'); + if ('free_templates' === key && !this.classList.contains('frm_inbox_dismiss')) { + return; + } + e.preventDefault(); + data = { + action: 'frm_inbox_dismiss', + key: key, + nonce: frmGlobal.nonce + }; + var isInboxSlideIn = 'frm_inbox_slide_in' === message.id; + if (isInboxSlideIn) { + message.classList.remove('s11-fadein'); + message.classList.add('s11-fadeout'); + message.addEventListener('animationend', function () { + return message.remove(); + }, { + once: true + }); + } + postAjax(data, function () { + if (isInboxSlideIn) { + return; + } + if (href !== '#') { + window.location = href; + return true; + } + fadeOut(message, function () { + if (null !== dismissedMessagesWrapper) { + var _dismissedMessage$que; + dismissedMessage.classList.remove('frm-fade'); + (_dismissedMessage$que = dismissedMessage.querySelector('.frm-inbox-message-heading')) === null || _dismissedMessage$que === void 0 || _dismissedMessage$que.removeChild(dismissedMessage.querySelector('.frm-inbox-message-heading .frm_inbox_dismiss')); + dismissedMessagesWrapper.append(dismissedMessage); + } + if (1 === message.parentNode.querySelectorAll('.frm-inbox-message-container').length) { + document.getElementById('frm_empty_inbox').classList.remove('frm_hidden'); + message.parentNode.closest('.frm-active').classList.add('frm-empty-inbox'); + showActiveCampaignForm(); + } + message.parentNode.removeChild(message); + }); + }); + }); + if (false === ((_document$getElementB6 = document.getElementById('frm_empty_inbox')) === null || _document$getElementB6 === void 0 ? void 0 : _document$getElementB6.classList.contains('frm_hidden'))) { + showActiveCampaignForm(); + } + }, + solutionInit: function solutionInit() { + jQuery(document).on('submit', '#frm-new-template', installTemplate); + }, + styleInit: function styleInit() { + var $previewWrapper = jQuery('.frm_image_preview_wrapper'); + $previewWrapper.on('click', '.frm_choose_image_box', addImageToOption); + $previewWrapper.on('click', '.frm_remove_image_option', removeImageFromOption); + wp.hooks.doAction('frm_style_editor_init'); + }, + customCSSInit: function customCSSInit() { + console.warn('Calling frmAdminBuild.customCSSInit is deprecated.'); + }, + globalSettingsInit: function globalSettingsInit() { + var licenseTab; + jQuery(document).on('click', '[data-frmuninstall]', uninstallNow); + initiateMultiselect(); + + // activate addon licenses + licenseTab = document.getElementById('licenses_settings'); + if (licenseTab !== null) { + jQuery(licenseTab).on('click', '.edd_frm_save_license', saveAddonLicense); + } + + // Solution install page + jQuery(document).on('click', '#frm-new-template button', installTemplateFieldset); + jQuery('#frm-dismissable-cta .dismiss').on('click', function (event) { + event.preventDefault(); + jQuery.post(ajaxurl, { + action: 'frm_lite_settings_upgrade', + nonce: frmGlobal.nonce + }); + jQuery('.settings-lite-cta').remove(); + }); + var captchaType = document.getElementById('frm_re_type'); + if (captchaType) { + captchaType.addEventListener('change', handleCaptchaTypeChange); + } + document.querySelector('.frm_captchas').addEventListener('change', function (event) { + var _document$querySelect8; + var captchaValueOnLoad = (_document$querySelect8 = document.querySelector('.frm_captchas input[checked="checked"]')) === null || _document$querySelect8 === void 0 ? void 0 : _document$querySelect8.value; + var showNote = event.target.value !== captchaValueOnLoad; + document.querySelector('.captcha_settings .frm_note_style').classList.toggle('frm_hidden', !showNote); + }); + + // Set fieldsUpdated to 0 to avoid the unsaved changes pop up. + frmDom.util.documentOn('submit', '.frm_settings_form', function () { + return fieldsUpdated = 0; + }); + var manageStyleSettings = document.getElementById('manage_styles_settings'); + if (manageStyleSettings) { + manageStyleSettings.addEventListener('change', function (event) { + var target = event.target; + if ('SELECT' !== target.nodeName || !target.dataset.name || target.getAttribute('name')) { + return; + } + target.setAttribute('name', target.dataset.name); + }); + } + var paymentsSettings = document.getElementById('payments_settings'); + var paymentSettingsTabs = paymentsSettings === null || paymentsSettings === void 0 ? void 0 : paymentsSettings.querySelectorAll('[name="frm_payment_section"]'); + if (paymentSettingsTabs) { + paymentSettingsTabs.forEach(function (element) { + element.addEventListener('change', function () { + if (!element.checked) { + return; + } + var label = paymentsSettings.querySelector("label[for=\"".concat(element.id, "\"]")); + if (label) { + label.setAttribute('aria-selected', 'true'); + } + paymentSettingsTabs.forEach(function (tab) { + if (tab === element) { + return; + } + var label = paymentsSettings.querySelector("label[for=\"".concat(tab.id, "\"]")); + if (label) { + label.setAttribute('aria-selected', 'false'); + } + }); + }); + }); + } + }, + exportInit: function exportInit() { + jQuery('.frm_form_importer').on('submit', startFormMigration); + jQuery(document.getElementById('frm_export_xml')).on('submit', validateExport); + jQuery('#frm_export_xml input, #frm_export_xml select').on('change', removeExportError); + jQuery('input[name="frm_import_file"]').on('change', checkCSVExtension); + document.querySelector('select[name="format"]').addEventListener('change', exportTypeChanged); + jQuery('input[name="frm_export_forms[]"]').on('click', preventMultipleExport); + initiateMultiselect(); + jQuery('.frm-feature-banner .dismiss').on('click', function (event) { + event.preventDefault(); + jQuery.post(ajaxurl, { + action: 'frm_dismiss_migrator', + plugin: this.id, + nonce: frmGlobal.nonce + }); + this.parentElement.remove(); + }); + showOrHideRepeaters(getExportOption()); + document.querySelector('#frm-export-select-all').addEventListener('change', function (event) { + document.querySelectorAll('[name="frm_export_forms[]"]').forEach(function (cb) { + return cb.checked = event.target.checked; + }); + }); + }, + inboxBannerInit: function inboxBannerInit() { + var banner = document.getElementById('frm_banner'); + if (!banner) { + return; + } + var dismissButton = banner.querySelector('.frm-banner-dismiss'); + document.addEventListener('click', function (event) { + if (event.target !== dismissButton) { + return; + } + var data = { + action: 'frm_inbox_dismiss', + key: banner.dataset.key, + nonce: frmGlobal.nonce + }; + postAjax(data, function () { + jQuery(banner).fadeOut(400, function () { + banner.remove(); + }); + }); + }); + }, + updateOpts: function updateOpts(fieldId, opts, modal) { + var separate = usingSeparateValues(fieldId), + action = isProductField(fieldId) ? 'frm_bulk_products' : 'frm_import_options'; + jQuery.ajax({ + type: 'POST', + url: ajaxurl, + data: { + action: action, + field_id: fieldId, + opts: opts, + separate: separate, + nonce: frmGlobal.nonce + }, + success: function success(html) { + document.getElementById('frm_field_' + fieldId + '_opts').innerHTML = html; + wp.hooks.doAction('frm_after_bulk_edit_opts', fieldId); + resetDisplayedOpts(fieldId); + if (typeof modal !== 'undefined') { + modal.dialog('close'); + document.getElementById('frm-update-bulk-opts').classList.remove('frm_loading_button'); + } + } + }); + }, + /* remove conditional logic if the field doesn't exist */ + triggerRemoveLogic: function triggerRemoveLogic(fieldID, metaName) { + jQuery('#frm_logic_' + fieldID + '_' + metaName + ' .frm_remove_tag').trigger('click'); + }, + downloadXML: function downloadXML(controller, ids, isTemplate) { + var url = ajaxurl + '?action=frm_' + controller + '_xml&ids=' + ids; + if (isTemplate !== null) { + url = url + '&is_template=' + isTemplate; + } + location.href = url; + }, + /** + * @since 5.0.04 + */ + hooks: { + applyFilters: function applyFilters(hookName) { + var _wp$hooks; + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key2 = 1; _key2 < _len; _key2++) { + args[_key2 - 1] = arguments[_key2]; + } + return (_wp$hooks = wp.hooks).applyFilters.apply(_wp$hooks, [hookName].concat(args)); + }, + addFilter: function addFilter(hookName, callback, priority) { + return wp.hooks.addFilter(hookName, 'formidable', callback, priority); + }, + doAction: function doAction(hookName) { + var _wp$hooks2; + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key3 = 1; _key3 < _len2; _key3++) { + args[_key3 - 1] = arguments[_key3]; + } + return (_wp$hooks2 = wp.hooks).doAction.apply(_wp$hooks2, [hookName].concat(args)); + }, + addAction: function addAction(hookName, callback, priority) { + return wp.hooks.addAction(hookName, 'formidable', callback, priority); + } + }, + applyZebraStriping: applyZebraStriping, + initModal: initModal, + infoModal: infoModal, + offsetModalY: offsetModalY, + adjustConditionalLogicOptionOrders: adjustConditionalLogicOptionOrders, + addRadioCheckboxOpt: addRadioCheckboxOpt, + installNewForm: installNewForm, + toggleAddonState: toggleAddonState, + purifyHtml: purifyHtml, + loadApiEmailForm: loadApiEmailForm, + addMyEmailAddress: addMyEmailAddress, + fillDropdownOpts: fillDropdownOpts, + showSaveAndReloadModal: showSaveAndReloadModal, + clearSettingsBox: clearSettingsBox, + deleteField: deleteField, + insertFormField: insertFormField, + confirmLinkClick: confirmLinkClick, + handleInsertFieldByDraggingResponse: handleInsertFieldByDraggingResponse, + handleAddFieldClickResponse: handleAddFieldClickResponse, + syncLayoutClasses: syncLayoutClasses, + moveFieldSettings: moveFieldSettings + }; +}; +window.frmAdminBuild = frmAdminBuildJS(); +jQuery(document).ready(function () { + var _document$querySelect9; + frmAdminBuild.init(); + frmDom.bootstrap.setupBootstrapDropdowns(convertOldBootstrapDropdownsToBootstrap4); + (_document$querySelect9 = document.querySelector('.preview.dropdown .frm-dropdown-toggle')) === null || _document$querySelect9 === void 0 || _document$querySelect9.setAttribute('data-toggle', 'dropdown'); + function convertOldBootstrapDropdownsToBootstrap4(frmDropdownMenu) { + var toggle = frmDropdownMenu.querySelector('.frm-dropdown-toggle'); + if (toggle) { + if (!toggle.hasAttribute('role')) { + toggle.setAttribute('role', 'button'); + } + if (!toggle.hasAttribute('tabindex')) { + toggle.setAttribute('tabindex', 0); + } + } + + // Convert' + res.data.name + ': ' + res.data.msg + '
';\n\t\t\t\t} else {\n\t\t\t\t\tstatusUpdate = 'Imported ' + res.data.name + '
';\n\t\t\t\t}\n\n\t\t\t\t$processSettings.find( '.status' ).prepend( statusUpdate );\n\t\t\t\t$processSettings.find( '.status' ).show();\n\n\t\t\t\t// Remove this form ID from the queue.\n\t\t\t\ts.importQueue = jQuery.grep( s.importQueue, function( value ) {\n\t\t\t\t\treturn value != formID;\n\t\t\t\t} );\n\t\t\t\ts.imported++;\n\n\t\t\t\tif ( s.importQueue.length === 0 ) {\n\t\t\t\t\t$processSettings.find( '.process-count' ).hide();\n\t\t\t\t\t$processSettings.find( '.forms-completed' ).text( s.imported );\n\t\t\t\t\t$processSettings.find( '.process-completed' ).show();\n\t\t\t\t} else {\n\t\t\t\t\t// Import next form in the queue.\n\t\t\t\t\t$processSettings.find( '.form-current' ).text( s.imported + 1 );\n\t\t\t\t\timportForm( $processSettings );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tfunction validateExport( e ) {\n\t\t/*jshint validthis:true */\n\t\te.preventDefault();\n\n\t\tlet s = false;\n\t\tconst $exportForms = jQuery( 'input[name=\"frm_export_forms[]\"]' );\n\n\t\tif ( ! jQuery( 'input[name=\"frm_export_forms[]\"]:checked' ).val() ) {\n\t\t\t$exportForms.closest( '.frm-table-box' ).addClass( 'frm_blank_field' );\n\t\t\ts = 'stop';\n\t\t}\n\n\t\tconst $exportType = jQuery( 'input[name=\"type[]\"]' );\n\t\tif ( ! jQuery( 'input[name=\"type[]\"]:checked' ).val() && $exportType.attr( 'type' ) === 'checkbox' ) {\n\t\t\t$exportType.closest( 'p' ).addClass( 'frm_blank_field' );\n\t\t\ts = 'stop';\n\t\t}\n\n\t\tif ( s === 'stop' ) {\n\t\t\treturn false;\n\t\t}\n\n\t\te.stopPropagation();\n\t\tthis.submit();\n\t}\n\n\tfunction removeExportError() {\n\t\t/*jshint validthis:true */\n\t\tconst t = jQuery( this ).closest( '.frm_blank_field' );\n\t\tif ( typeof t === 'undefined' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst $thisName = this.name;\n\t\tif ( $thisName === 'type[]' && jQuery( 'input[name=\"type[]\"]:checked' ).val() ) {\n\t\t\tt.removeClass( 'frm_blank_field' );\n\t\t} else if ( $thisName === 'frm_export_forms[]' && jQuery( this ).val() ) {\n\t\t\tt.removeClass( 'frm_blank_field' );\n\t\t}\n\t}\n\n\tfunction checkCSVExtension() {\n\t\t/*jshint validthis:true */\n\t\tconst f = jQuery( this ).val();\n\t\tconst re = /\\.csv$/i;\n\t\tif ( f.match( re ) !== null ) {\n\t\t\tjQuery( '.show_csv' ).fadeIn();\n\t\t} else {\n\t\t\tjQuery( '.show_csv' ).fadeOut();\n\t\t}\n\t}\n\n\tfunction getExportOption() {\n\t\tconst exportFormatSelect = document.querySelector( 'select[name=\"format\"]' );\n\t\tif ( exportFormatSelect ) {\n\t\t\treturn exportFormatSelect.value;\n\t\t}\n\t\treturn '';\n\t}\n\n\tfunction exportTypeChanged( event ) {\n\t\tconst value = event.target.value;\n\t\tshowOrHideRepeaters( value );\n\t\tcheckExportTypes.call( event.target );\n\t\tcheckSelectedAllFormsCheckbox( value );\n\t}\n\n\tfunction checkSelectedAllFormsCheckbox( exportType ) {\n\t\tconst selectAllCheckbox = document.getElementById( 'frm-export-select-all' );\n\t\tif ( exportType === 'csv' ) {\n\t\t\tselectAllCheckbox.checked = false;\n\t\t\tselectAllCheckbox.disabled = true;\n\t\t} else {\n\t\t\tselectAllCheckbox.disabled = false;\n\t\t}\n\t}\n\n\tfunction checkExportTypes() {\n\t\t/*jshint validthis:true */\n\t\tconst $dropdown = jQuery( this );\n\t\tconst $selected = $dropdown.find( ':selected' );\n\t\tconst s = $selected.data( 'support' );\n\n\t\tconst multiple = s.indexOf( '|' );\n\t\tjQuery( 'input[name=\"type[]\"]' ).each( function() {\n\t\t\tthis.checked = false;\n\t\t\tif ( s.indexOf( this.value ) >= 0 ) {\n\t\t\t\tthis.disabled = false;\n\t\t\t\tif ( multiple === -1 ) {\n\t\t\t\t\tthis.checked = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.disabled = true;\n\t\t\t}\n\t\t} );\n\n\t\tif ( $dropdown.val() === 'csv' ) {\n\t\t\tjQuery( '.csv_opts' ).show();\n\t\t\tjQuery( '.xml_opts' ).hide();\n\t\t} else {\n\t\t\tjQuery( '.csv_opts' ).hide();\n\t\t\tjQuery( '.xml_opts' ).show();\n\t\t}\n\n\t\tconst c = $selected.data( 'count' );\n\t\tconst exportField = jQuery( 'input[name=\"frm_export_forms[]\"]' );\n\t\tif ( c === 'single' ) {\n\t\t\texportField.prop( 'multiple', false );\n\t\t\texportField.prop( 'checked', false );\n\t\t} else {\n\t\t\texportField.prop( 'multiple', true );\n\t\t\texportField.prop( 'disabled', false );\n\t\t}\n\t\t$dropdown.trigger( 'change' );\n\t}\n\n\tfunction showOrHideRepeaters( exportOption ) {\n\t\tif ( exportOption === '' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst repeaters = document.querySelectorAll( '.frm-is-repeater' );\n\t\tif ( ! repeaters.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( exportOption === 'csv' ) {\n\t\t\trepeaters.forEach( form => {\n\t\t\t\tform.classList.remove( 'frm_hidden' );\n\t\t\t} );\n\t\t} else {\n\t\t\trepeaters.forEach( form => {\n\t\t\t\tform.classList.add( 'frm_hidden' );\n\t\t\t} );\n\t\t}\n\n\t\tsearchContent.call( document.querySelector( '.frm-auto-search' ) );\n\t}\n\n\tfunction preventMultipleExport() {\n\t\tconst type = jQuery( 'select[name=format]' ),\n\t\t\tselected = type.find( ':selected' ),\n\t\t\tcount = selected.data( 'count' ),\n\t\t\texportField = jQuery( 'input[name=\"frm_export_forms[]\"]' );\n\n\t\tif ( count === 'single' ) {\n\t\t\t// Disable all other fields to prevent multiple selections.\n\t\t\tif ( this.checked ) {\n\t\t\t\texportField.prop( 'disabled', true );\n\t\t\t\tthis.removeAttribute( 'disabled' );\n\t\t\t} else {\n\t\t\t\texportField.prop( 'disabled', false );\n\t\t\t}\n\t\t} else {\n\t\t\texportField.prop( 'disabled', false );\n\t\t}\n\t}\n\n\tfunction initiateMultiselect() {\n\t\tjQuery( '.frm_multiselect' ).hide().each( frmDom.bootstrap.multiselect.init );\n\t}\n\n\t/* Addons page */\n\tfunction installMultipleAddons( e ) {\n\t\te.preventDefault();\n\t\ttoggleAddonState( this, 'frm_multiple_addons' );\n\t}\n\n\tfunction activateAddon( e ) {\n\t\te.preventDefault();\n\t\ttoggleAddonState( this, 'frm_activate_addon' );\n\t}\n\n\tfunction installAddon( e ) {\n\t\te.preventDefault();\n\t\ttoggleAddonState( this, 'frm_install_addon' );\n\t}\n\n\tfunction toggleAddonState( clicked, action ) {\n\t\tlet button, plugin, el, message;\n\n\t\t// Remove any leftover error messages, output an icon and get the plugin basename that needs to be activated.\n\t\tjQuery( '.frm-addon-error' ).remove();\n\t\tbutton = jQuery( clicked );\n\t\tplugin = button.attr( 'rel' );\n\t\tel = button.parent();\n\t\tmessage = el.parent().find( '.addon-status-label' );\n\n\t\tbutton.addClass( 'frm_loading_button' );\n\n\t\t// Process the Ajax to perform the activation.\n\t\tjQuery.ajax( {\n\t\t\turl: ajaxurl,\n\t\t\ttype: 'POST',\n\t\t\tasync: true,\n\t\t\tcache: false,\n\t\t\tdataType: 'json',\n\t\t\tdata: {\n\t\t\t\taction: action,\n\t\t\t\tnonce: frmGlobal.nonce,\n\t\t\t\tplugin: plugin\n\t\t\t},\n\t\t\tsuccess: function( response ) {\n\t\t\t\tresponse = response?.data ?? response;\n\n\t\t\t\tlet saveAndReload;\n\n\t\t\t\tif ( 'string' !== typeof response && 'string' === typeof response.message ) {\n\t\t\t\t\tif ( 'undefined' !== typeof response.saveAndReload ) {\n\t\t\t\t\t\tsaveAndReload = response.saveAndReload;\n\t\t\t\t\t}\n\t\t\t\t\tresponse = response.message;\n\t\t\t\t}\n\n\t\t\t\tconst error = extractErrorFromAddOnResponse( response );\n\t\t\t\tif ( error ) {\n\t\t\t\t\taddonError( error, el, button );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tafterAddonInstall( response, button, message, el, saveAndReload, action );\n\n\t\t\t\t/**\n\t\t\t\t * Trigger an action after successfully toggling the addon state.\n\t\t\t\t *\n\t\t\t\t * @param {Object} response\n\t\t\t\t */\n\t\t\t\twp.hooks.doAction( 'frm_update_addon_state', response );\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\tbutton.removeClass( 'frm_loading_button' );\n\t\t\t}\n\t\t} );\n\t}\n\n\tfunction installAddonWithCreds( e ) {\n\t\t// Prevent the default action, let the user know we are attempting to install again and go with it.\n\t\te.preventDefault();\n\n\t\t// Now let's make another Ajax request once the user has submitted their credentials.\n\t\tconst proceed = jQuery( this );\n\t\tconst el = proceed.parent().parent();\n\t\tconst plugin = proceed.attr( 'rel' );\n\n\t\tproceed.addClass( 'frm_loading_button' );\n\n\t\tjQuery.ajax( {\n\t\t\turl: ajaxurl,\n\t\t\ttype: 'POST',\n\t\t\tasync: true,\n\t\t\tcache: false,\n\t\t\tdataType: 'json',\n\t\t\tdata: {\n\t\t\t\taction: 'frm_install_addon',\n\t\t\t\tnonce: frmAdminJs.nonce,\n\t\t\t\tplugin: plugin,\n\t\t\t\thostname: el.find( '#hostname' ).val(),\n\t\t\t\tusername: el.find( '#username' ).val(),\n\t\t\t\tpassword: el.find( '#password' ).val()\n\t\t\t},\n\t\t\tsuccess: function( response ) {\n\t\t\t\tresponse = response?.data ?? response;\n\n\t\t\t\tconst error = extractErrorFromAddOnResponse( response );\n\t\t\t\tif ( error ) {\n\t\t\t\t\taddonError( error, el, proceed );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tafterAddonInstall( response, proceed, message, el );\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\tproceed.removeClass( 'frm_loading_button' );\n\t\t\t}\n\t\t} );\n\t}\n\n\tfunction afterAddonInstall( response, button, message, el, saveAndReload, action = 'frm_activate_addon' ) {\n\t\tconst addonStatuses = document.querySelectorAll( '.frm-addon-status' );\n\t\taddonStatuses.forEach(\n\t\t\taddonStatus => {\n\t\t\t\taddonStatus.textContent = response;\n\t\t\t\taddonStatus.style.display = 'block';\n\t\t\t}\n\t\t);\n\n\t\t// The Ajax request was successful, so let's update the output.\n\t\tbutton.css( { opacity: '0' } );\n\n\t\tdocument.querySelectorAll( '.frm-oneclick' ).forEach(\n\t\t\toneClick => {\n\t\t\t\toneClick.style.display = 'none';\n\t\t\t}\n\t\t);\n\n\t\tjQuery( '#frm_upgrade_modal h2' ).hide();\n\t\tjQuery( '#frm_upgrade_modal .frm_lock_icon' ).addClass( 'frm_lock_open_icon' );\n\t\tjQuery( '#frm_upgrade_modal .frm_lock_icon use' ).attr( 'xlink:href', '#frm_lock_open_icon' );\n\n\t\t// Proceed with CSS changes\n\t\tconst actionMap = {\n\t\t\tfrm_activate_addon: { class: 'frm-addon-active', message: frmAdminJs.active },\n\t\t\tfrm_deactivate_addon: { class: 'frm-addon-installed', message: frmAdminJs.installed },\n\t\t\tfrm_uninstall_addon: { class: 'frm-addon-not-installed', message: frmAdminJs.not_installed }\n\t\t};\n\t\tactionMap.frm_install_addon = actionMap.frm_activate_addon;\n\n\t\tconst messageElement = message[ 0 ];\n\t\tif ( messageElement ) {\n\t\t\tmessageElement.textContent = actionMap[ action ].message;\n\t\t}\n\n\t\tconst parentElement = el[ 0 ].parentElement;\n\t\tparentElement.classList.remove( 'frm-addon-not-installed', 'frm-addon-installed', 'frm-addon-active' );\n\t\tparentElement.classList.add( actionMap[ action ].class );\n\n\t\tconst buttonElement = button[ 0 ];\n\t\tbuttonElement.classList.remove( 'frm_loading_button' );\n\n\t\t// Maybe refresh import and SMTP pages\n\t\tconst refreshPage = document.querySelectorAll( '.frm-admin-page-import, #frm-admin-smtp, #frm-welcome' );\n\t\tif ( refreshPage.length > 0 ) {\n\t\t\twindow.location.reload();\n\t\t\treturn;\n\t\t}\n\n\t\tif ( [ 'settings', 'form_builder' ].includes( saveAndReload ) ) {\n\t\t\taddonStatuses.forEach(\n\t\t\t\taddonStatus => {\n\t\t\t\t\tconst inModal = null !== addonStatus.closest( '#frm_upgrade_modal' );\n\t\t\t\t\taddonStatus.appendChild( getSaveAndReloadSettingsOptions( saveAndReload, inModal ) );\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\tfunction getSaveAndReloadSettingsOptions( saveAndReload, inModal ) {\n\t\tconst className = 'frm-save-and-reload-options';\n\t\tconst children = [ saveAndReloadSettingsButton( saveAndReload ) ];\n\t\tif ( inModal ) {\n\t\t\tchildren.push( closePopupButton() );\n\t\t}\n\t\treturn div( { className, children } );\n\t}\n\n\tfunction saveAndReloadSettingsButton( saveAndReload ) {\n\t\tconst button = document.createElement( 'button' );\n\t\tbutton.classList.add( 'frm-save-and-reload', 'button', 'button-primary', 'frm-button-primary' );\n\t\tbutton.textContent = __( 'Save and Reload', 'formidable' );\n\t\tbutton.addEventListener( 'click', () => {\n\t\t\tif ( saveAndReload === 'form_builder' ) {\n\t\t\t\tsaveAndReloadFormBuilder();\n\t\t\t} else if ( saveAndReload === 'settings' ) {\n\t\t\t\tsaveAndReloadSettings();\n\t\t\t}\n\t\t} );\n\t\treturn button;\n\t}\n\n\tfunction closePopupButton() {\n\t\tconst a = document.createElement( 'a' );\n\t\ta.setAttribute( 'href', '#' );\n\t\ta.classList.add( 'button', 'button-secondary', 'frm-button-secondary', 'dismiss' );\n\t\ta.textContent = __( 'Close', 'formidable' );\n\t\treturn a;\n\t}\n\n\tfunction extractErrorFromAddOnResponse( response ) {\n\t\tif ( typeof response !== 'string' ) {\n\t\t\tif ( typeof response.success !== 'undefined' && response.success ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( response.form ) {\n\t\t\t\tif ( jQuery( response.form ).is( '#message' ) ) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmessage: jQuery( response.form ).find( 'p' ).html()\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tfunction addonError( response, el, button ) {\n\t\tif ( response.form ) {\n\t\t\tjQuery( '.frm-inline-error' ).remove();\n\t\t\tbutton.closest( '.frm-card' )\n\t\t\t\t.html( response.form )\n\t\t\t\t.css( { padding: 5 } )\n\t\t\t\t.find( '#upgrade' )\n\t\t\t\t.attr( 'rel', button.attr( 'rel' ) )\n\t\t\t\t.on( 'click', installAddonWithCreds );\n\t\t} else {\n\t\t\tel.append( '' + response.message + '
' + response.message + '
' + res.data.name + ': ' + res.data.msg + '
';\n\t\t\t\t} else {\n\t\t\t\t\tstatusUpdate = 'Imported ' + res.data.name + '
';\n\t\t\t\t}\n\n\t\t\t\t$processSettings.find( '.status' ).prepend( statusUpdate );\n\t\t\t\t$processSettings.find( '.status' ).show();\n\n\t\t\t\t// Remove this form ID from the queue.\n\t\t\t\ts.importQueue = jQuery.grep( s.importQueue, function( value ) {\n\t\t\t\t\treturn value != formID;\n\t\t\t\t} );\n\t\t\t\ts.imported++;\n\n\t\t\t\tif ( s.importQueue.length === 0 ) {\n\t\t\t\t\t$processSettings.find( '.process-count' ).hide();\n\t\t\t\t\t$processSettings.find( '.forms-completed' ).text( s.imported );\n\t\t\t\t\t$processSettings.find( '.process-completed' ).show();\n\t\t\t\t} else {\n\t\t\t\t\t// Import next form in the queue.\n\t\t\t\t\t$processSettings.find( '.form-current' ).text( s.imported + 1 );\n\t\t\t\t\timportForm( $processSettings );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n\n\tfunction validateExport( e ) {\n\t\t/*jshint validthis:true */\n\t\te.preventDefault();\n\n\t\tlet s = false;\n\t\tconst $exportForms = jQuery( 'input[name=\"frm_export_forms[]\"]' );\n\n\t\tif ( ! jQuery( 'input[name=\"frm_export_forms[]\"]:checked' ).val() ) {\n\t\t\t$exportForms.closest( '.frm-table-box' ).addClass( 'frm_blank_field' );\n\t\t\ts = 'stop';\n\t\t}\n\n\t\tconst $exportType = jQuery( 'input[name=\"type[]\"]' );\n\t\tif ( ! jQuery( 'input[name=\"type[]\"]:checked' ).val() && $exportType.attr( 'type' ) === 'checkbox' ) {\n\t\t\t$exportType.closest( 'p' ).addClass( 'frm_blank_field' );\n\t\t\ts = 'stop';\n\t\t}\n\n\t\tif ( s === 'stop' ) {\n\t\t\treturn false;\n\t\t}\n\n\t\te.stopPropagation();\n\t\tthis.submit();\n\t}\n\n\tfunction removeExportError() {\n\t\t/*jshint validthis:true */\n\t\tconst t = jQuery( this ).closest( '.frm_blank_field' );\n\t\tif ( typeof t === 'undefined' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst $thisName = this.name;\n\t\tif ( $thisName === 'type[]' && jQuery( 'input[name=\"type[]\"]:checked' ).val() ) {\n\t\t\tt.removeClass( 'frm_blank_field' );\n\t\t} else if ( $thisName === 'frm_export_forms[]' && jQuery( this ).val() ) {\n\t\t\tt.removeClass( 'frm_blank_field' );\n\t\t}\n\t}\n\n\tfunction checkCSVExtension() {\n\t\t/*jshint validthis:true */\n\t\tconst f = jQuery( this ).val();\n\t\tconst re = /\\.csv$/i;\n\t\tif ( f.match( re ) !== null ) {\n\t\t\tjQuery( '.show_csv' ).fadeIn();\n\t\t} else {\n\t\t\tjQuery( '.show_csv' ).fadeOut();\n\t\t}\n\t}\n\n\tfunction getExportOption() {\n\t\tconst exportFormatSelect = document.querySelector( 'select[name=\"format\"]' );\n\t\tif ( exportFormatSelect ) {\n\t\t\treturn exportFormatSelect.value;\n\t\t}\n\t\treturn '';\n\t}\n\n\tfunction exportTypeChanged( event ) {\n\t\tconst value = event.target.value;\n\t\tshowOrHideRepeaters( value );\n\t\tcheckExportTypes.call( event.target );\n\t\tcheckSelectedAllFormsCheckbox( value );\n\t}\n\n\tfunction checkSelectedAllFormsCheckbox( exportType ) {\n\t\tconst selectAllCheckbox = document.getElementById( 'frm-export-select-all' );\n\t\tif ( exportType === 'csv' ) {\n\t\t\tselectAllCheckbox.checked = false;\n\t\t\tselectAllCheckbox.disabled = true;\n\t\t} else {\n\t\t\tselectAllCheckbox.disabled = false;\n\t\t}\n\t}\n\n\tfunction checkExportTypes() {\n\t\t/*jshint validthis:true */\n\t\tconst $dropdown = jQuery( this );\n\t\tconst $selected = $dropdown.find( ':selected' );\n\t\tconst s = $selected.data( 'support' );\n\n\t\tconst multiple = s.indexOf( '|' );\n\t\tjQuery( 'input[name=\"type[]\"]' ).each( function() {\n\t\t\tthis.checked = false;\n\t\t\tif ( s.indexOf( this.value ) >= 0 ) {\n\t\t\t\tthis.disabled = false;\n\t\t\t\tif ( multiple === -1 ) {\n\t\t\t\t\tthis.checked = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.disabled = true;\n\t\t\t}\n\t\t} );\n\n\t\tif ( $dropdown.val() === 'csv' ) {\n\t\t\tjQuery( '.csv_opts' ).show();\n\t\t\tjQuery( '.xml_opts' ).hide();\n\t\t} else {\n\t\t\tjQuery( '.csv_opts' ).hide();\n\t\t\tjQuery( '.xml_opts' ).show();\n\t\t}\n\n\t\tconst c = $selected.data( 'count' );\n\t\tconst exportField = jQuery( 'input[name=\"frm_export_forms[]\"]' );\n\t\tif ( c === 'single' ) {\n\t\t\texportField.prop( 'multiple', false );\n\t\t\texportField.prop( 'checked', false );\n\t\t} else {\n\t\t\texportField.prop( 'multiple', true );\n\t\t\texportField.prop( 'disabled', false );\n\t\t}\n\t\t$dropdown.trigger( 'change' );\n\t}\n\n\tfunction showOrHideRepeaters( exportOption ) {\n\t\tif ( exportOption === '' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst repeaters = document.querySelectorAll( '.frm-is-repeater' );\n\t\tif ( ! repeaters.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( exportOption === 'csv' ) {\n\t\t\trepeaters.forEach( form => {\n\t\t\t\tform.classList.remove( 'frm_hidden' );\n\t\t\t} );\n\t\t} else {\n\t\t\trepeaters.forEach( form => {\n\t\t\t\tform.classList.add( 'frm_hidden' );\n\t\t\t} );\n\t\t}\n\n\t\tsearchContent.call( document.querySelector( '.frm-auto-search' ) );\n\t}\n\n\tfunction preventMultipleExport() {\n\t\tconst type = jQuery( 'select[name=format]' ),\n\t\t\tselected = type.find( ':selected' ),\n\t\t\tcount = selected.data( 'count' ),\n\t\t\texportField = jQuery( 'input[name=\"frm_export_forms[]\"]' );\n\n\t\tif ( count === 'single' ) {\n\t\t\t// Disable all other fields to prevent multiple selections.\n\t\t\tif ( this.checked ) {\n\t\t\t\texportField.prop( 'disabled', true );\n\t\t\t\tthis.removeAttribute( 'disabled' );\n\t\t\t} else {\n\t\t\t\texportField.prop( 'disabled', false );\n\t\t\t}\n\t\t} else {\n\t\t\texportField.prop( 'disabled', false );\n\t\t}\n\t}\n\n\tfunction initiateMultiselect() {\n\t\tjQuery( '.frm_multiselect' ).hide().each( frmDom.bootstrap.multiselect.init );\n\t}\n\n\t/* Addons page */\n\tfunction installMultipleAddons( e ) {\n\t\te.preventDefault();\n\t\ttoggleAddonState( this, 'frm_multiple_addons' );\n\t}\n\n\tfunction activateAddon( e ) {\n\t\te.preventDefault();\n\t\ttoggleAddonState( this, 'frm_activate_addon' );\n\t}\n\n\tfunction installAddon( e ) {\n\t\te.preventDefault();\n\t\ttoggleAddonState( this, 'frm_install_addon' );\n\t}\n\n\tfunction toggleAddonState( clicked, action ) {\n\t\tconst addonState = require( './addon-state' );\n\t\taddonState.toggleAddonState( clicked, action );\n\t}\n\n\tfunction installAddonWithCreds( e ) {\n\t\t// Prevent the default action, let the user know we are attempting to install again and go with it.\n\t\te.preventDefault();\n\n\t\t// Now let's make another Ajax request once the user has submitted their credentials.\n\t\tconst proceed = jQuery( this );\n\t\tconst el = proceed.parent().parent();\n\t\tconst plugin = proceed.attr( 'rel' );\n\n\t\tproceed.addClass( 'frm_loading_button' );\n\n\t\tjQuery.ajax( {\n\t\t\turl: ajaxurl,\n\t\t\ttype: 'POST',\n\t\t\tasync: true,\n\t\t\tcache: false,\n\t\t\tdataType: 'json',\n\t\t\tdata: {\n\t\t\t\taction: 'frm_install_addon',\n\t\t\t\tnonce: frmAdminJs.nonce,\n\t\t\t\tplugin: plugin,\n\t\t\t\thostname: el.find( '#hostname' ).val(),\n\t\t\t\tusername: el.find( '#username' ).val(),\n\t\t\t\tpassword: el.find( '#password' ).val()\n\t\t\t},\n\t\t\tsuccess: function( response ) {\n\t\t\t\tresponse = response?.data ?? response;\n\n\t\t\t\tconst error = extractErrorFromAddOnResponse( response );\n\t\t\t\tif ( error ) {\n\t\t\t\t\taddonError( error, el, proceed );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tafterAddonInstall( response, proceed, message, el );\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\tproceed.removeClass( 'frm_loading_button' );\n\t\t\t}\n\t\t} );\n\t}\n\n\tfunction afterAddonInstall( response, button, message, el, saveAndReload, action = 'frm_activate_addon' ) {\n\t\tconst addonState = require( './addon-state' );\n\t\taddonState.afterAddonInstall( response, button, message, el, saveAndReload, action );\n\t}\n\n\tfunction extractErrorFromAddOnResponse( response ) {\n\t\tconst addonState = require( './addon-state' );\n\t\treturn addonState.extractErrorFromAddOnResponse( response );\n\t}\n\n\tfunction addonError( response, el, button ) {\n\t\tconst addonState = require( './addon-state' );\n\t\taddonState.addonError( response, el, button );\n\t}\n\n\t/* Templates */\n\tfunction showActiveCampaignForm() {\n\t\tloadApiEmailForm();\n\t}\n\n\tfunction handleApiFormError( inputId, errorId, type, message ) {\n\t\tconst $error = jQuery( errorId );\n\t\t$error.removeClass( 'frm_hidden' ).attr( 'frm-error', type );\n\n\t\tif ( typeof message !== 'undefined' ) {\n\t\t\t$error.find( 'span[frm-error=\"' + type + '\"]' ).text( message );\n\t\t}\n\n\t\tjQuery( inputId ).one( 'keyup', function() {\n\t\t\t$error.addClass( 'frm_hidden' );\n\t\t} );\n\t}\n\n\tfunction handleEmailAddressError( type ) {\n\t\thandleApiFormError( '#frm_leave_email', '#frm_leave_email_error', type );\n\t}\n\n\tfunction loadApiEmailForm() {\n\t\tconst formContainer = document.getElementById( 'frmapi-email-form' );\n\t\tjQuery.ajax( {\n\t\t\tdataType: 'json',\n\t\t\turl: formContainer.getAttribute( 'data-url' ),\n\t\t\tsuccess: function( json ) {\n\t\t\t\tlet form = json.renderedHtml;\n\t\t\t\tform = form.replace( /]*(formidableforms.css|action=frmpro_css)[^>]*>/gi, '' );\n\t\t\t\tformContainer.innerHTML = form;\n\t\t\t}\n\t\t} );\n\t}\n\n\tfunction initAutocomplete( container ) {\n\t\tfrmDom.autocomplete.initSelectionAutocomplete( container );\n\t}\n\n\tfunction nextInstallStep( thisStep ) {\n\t\tthisStep.classList.add( 'frm_grey' );\n\t\tthisStep.nextElementSibling.classList.remove( 'frm_grey' );\n\t}\n\n\tfunction installTemplateFieldset( e ) {\n\t\t/*jshint validthis:true */\n\t\tconst fieldset = this.parentNode.parentNode,\n\t\t\taction = fieldset.elements.type.value,\n\t\t\tbutton = this;\n\t\te.preventDefault();\n\t\tbutton.classList.add( 'frm_loading_button' );\n\t\tinstallNewForm( fieldset, action, button );\n\t}\n\n\tfunction installTemplate( e ) {\n\t\t/*jshint validthis:true */\n\t\tconst action = this.elements.type.value,\n\t\t\tbutton = this.querySelector( 'button' );\n\t\te.preventDefault();\n\t\tbutton.classList.add( 'frm_loading_button' );\n\t\tinstallNewForm( this, action, button );\n\t}\n\n\tfunction installNewForm( form, action, button ) {\n\t\tconst formData = formToData( form );\n\t\tconst formName = formData.template_name;\n\t\tconst formDesc = formData.template_desc;\n\t\tconst link = form.elements.link.value;\n\n\t\tlet data = {\n\t\t\taction: action,\n\t\t\txml: link,\n\t\t\tname: formName,\n\t\t\tdesc: formDesc,\n\t\t\tform: JSON.stringify( formData ),\n\t\t\tnonce: frmGlobal.nonce\n\t\t};\n\n\t\tconst hookName = 'frm_before_install_new_form';\n\t\tconst filterArgs = { formData };\n\t\tdata = wp.hooks.applyFilters( hookName, data, filterArgs );\n\n\t\tpostAjax( data, function( response ) {\n\t\t\tif ( typeof response.redirect !== 'undefined' ) {\n\t\t\t\tconst redirect = response.redirect;\n\t\t\t\tif ( typeof form.elements.redirect === 'undefined' ) {\n\t\t\t\t\twindow.location = redirect;\n\t\t\t\t} else {\n\t\t\t\t\tconst href = document.getElementById( 'frm-redirect-link' );\n\t\t\t\t\tif ( typeof link !== 'undefined' && href !== null ) {\n\t\t\t\t\t\t// Show the next installation step.\n\t\t\t\t\t\thref.setAttribute( 'href', redirect );\n\t\t\t\t\t\thref.classList.remove( 'frm_grey', 'disabled' );\n\t\t\t\t\t\tnextInstallStep( form.parentNode.parentNode );\n\t\t\t\t\t\tbutton.classList.add( 'frm_grey', 'disabled' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tjQuery( '.spinner' ).css( 'visibility', 'hidden' );\n\n\t\t\t\t// Show response.message\n\t\t\t\tif ( 'string' === typeof response.message ) {\n\t\t\t\t\tshowInstallFormErrorModal( response.message );\n\t\t\t\t}\n\t\t\t}\n\t\t\tbutton.classList.remove( 'frm_loading_button' );\n\t\t} );\n\t}\n\n\tfunction showInstallFormErrorModal( message ) {\n\t\tconst modalContent = div( message );\n\t\tmodalContent.style.padding = '20px 40px';\n\t\tconst modal = frmDom.modal.maybeCreateModal(\n\t\t\t'frmInstallFormErrorModal',\n\t\t\t{\n\t\t\t\ttitle: __( 'Unable to install template', 'formidable' ),\n\t\t\t\tcontent: modalContent\n\t\t\t}\n\t\t);\n\t\tmodal.classList.add( 'frm_common_modal' );\n\t}\n\n\tfunction handleCaptchaTypeChange( e ) {\n\t\tconst thresholdContainer = document.getElementById( 'frm_captcha_threshold_container' );\n\t\tif ( thresholdContainer ) {\n\t\t\tthresholdContainer.classList.toggle( 'frm_hidden', 'v3' !== e.target.value );\n\t\t}\n\t}\n\n\tfunction trashTemplate( e ) {\n\t\t/*jshint validthis:true */\n\t\tconst id = this.getAttribute( 'data-id' );\n\t\te.preventDefault();\n\n\t\tdata = {\n\t\t\taction: 'frm_forms_trash',\n\t\t\tid: id,\n\t\t\tnonce: frmGlobal.nonce\n\t\t};\n\t\tpostAjax( data, function() {\n\t\t\tconst card = document.getElementById( 'frm-template-custom-' + id );\n\t\t\tfadeOut( card, function() {\n\t\t\t\tcard.parentNode.removeChild( card );\n\t\t\t} );\n\t\t} );\n\t}\n\n\tfunction searchContent() {\n\t\t/*jshint validthis:true */\n\t\tlet i,\n\t\t\tregEx = false,\n\t\t\tsearchText = this.value.toLowerCase(),\n\t\t\ttoSearch = this.getAttribute( 'data-tosearch' ),\n\t\t\titems = document.getElementsByClassName( toSearch );\n\n\t\tif ( this.tagName === 'SELECT' ) {\n\t\t\tsearchText = selectedOptions( this );\n\t\t\tsearchText = searchText.join( '|' ).toLowerCase();\n\t\t\tregEx = true;\n\t\t}\n\n\t\tif ( toSearch === 'frm-action' && searchText !== '' ) {\n\t\t\tconst addons = document.getElementById( 'frm_email_addon_menu' ).classList;\n\t\t\taddons.remove( 'frm-all-actions' );\n\t\t\taddons.add( 'frm-limited-actions' );\n\t\t}\n\n\t\tfor ( i = 0; i < items.length; i++ ) {\n\t\t\tconst innerText = items[ i ].innerText.toLowerCase();\n\n\t\t\tconst itemCanBeShown = ! ( getExportOption() === 'xml' && items[ i ].classList.contains( 'frm-is-repeater' ) );\n\t\t\tif ( searchText === '' ) {\n\t\t\t\tif ( itemCanBeShown && checkContextualShortcode( items[ i ] ) ) {\n\t\t\t\t\titems[ i ].classList.remove( 'frm_hidden' );\n\t\t\t\t}\n\t\t\t\titems[ i ].classList.remove( 'frm-search-result' );\n\t\t\t} else if ( ( regEx && new RegExp( searchText ).test( innerText ) ) || innerText.indexOf( searchText ) >= 0 || textMatchesPlural( innerText, searchText ) ) {\n\t\t\t\tif ( itemCanBeShown && checkContextualShortcode( items[ i ] ) ) {\n\t\t\t\t\titems[ i ].classList.remove( 'frm_hidden' );\n\t\t\t\t}\n\t\t\t\titems[ i ].classList.add( 'frm-search-result' );\n\t\t\t} else {\n\t\t\t\titems[ i ].classList.add( 'frm_hidden' );\n\t\t\t\titems[ i ].classList.remove( 'frm-search-result' );\n\t\t\t}\n\t\t}\n\n\t\t// Updates the visibility of category headings based on search results.\n\t\tupdateCatHeadingVisibility();\n\n\t\tjQuery( this ).trigger( 'frmAfterSearch' );\n\t}\n\n\t/**\n\t * Allow a search for \"signatures\" to still match \"signature\" for example when searching fields.\n\t *\n\t * @since 6.15\n\t *\n\t * @param {string} text The text in the element we are checking for a match.\n\t * @param {string} searchText The text value that is being searched.\n\t * @return {boolean}\n\t */\n\tfunction textMatchesPlural( text, searchText ) {\n\t\tif ( searchText === 's' ) {\n\t\t\t// Don't match everything when just \"s\" is searched.\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( text[ text.length - 1 ] === 's' ) {\n\t\t\t// Do not match something with double s if the text already ends in s.\n\t\t\treturn false;\n\t\t}\n\n\t\treturn ( text + 's' ).indexOf( searchText ) >= 0;\n\t}\n\n\t/**\n\t * Updates the visibility of category headings based on search results.\n\t * If all associated fields are hidden (indicating no search matches),\n\t * the heading is hidden.\n\t *\n\t * @since 6.4.1\n\t */\n\tfunction updateCatHeadingVisibility() {\n\t\tconst insertFieldsElement = document.querySelector( '#frm-insert-fields' );\n\t\tif ( ! insertFieldsElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst headingElements = insertFieldsElement.querySelectorAll( ':scope > .frm-with-line' );\n\t\theadingElements.forEach( heading => {\n\t\t\tconst fieldsListElement = heading.nextElementSibling;\n\t\t\tif ( ! fieldsListElement ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst listItemElements = fieldsListElement.querySelectorAll( ':scope > li.frmbutton' );\n\t\t\tconst allHidden = Array.from( listItemElements ).every( li => li.classList.contains( 'frm_hidden' ) );\n\n\t\t\t// Add or remove class based on `allHidden` condition\n\t\t\theading.classList.toggle( 'frm_hidden', allHidden );\n\t\t} );\n\t}\n\n\tfunction stopPropagation( e ) {\n\t\te.stopPropagation();\n\t}\n\n\t/* Helpers */\n\n\tfunction selectedOptions( select ) {\n\t\tlet opt,\n\t\t\tresult = [],\n\t\t\toptions = select && select.options;\n\n\t\tfor ( let i = 0, iLen = options.length; i < iLen; i++ ) {\n\t\t\topt = options[ i ];\n\n\t\t\tif ( opt.selected ) {\n\t\t\t\tresult.push( opt.value );\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tfunction triggerEvent( element, event ) {\n\t\tconst evt = document.createEvent( 'HTMLEvents' );\n\t\tevt.initEvent( event, false, true );\n\t\telement.dispatchEvent( evt );\n\t}\n\n\tfunction postAjax( data, success ) {\n\t\tlet response;\n\n\t\tconst xmlHttp = new XMLHttpRequest();\n\t\tconst params = typeof data === 'string' ? data : Object.keys( data ).map(\n\t\t\tfunction( k ) {\n\t\t\t\treturn encodeURIComponent( k ) + '=' + encodeURIComponent( data[ k ] );\n\t\t\t}\n\t\t).join( '&' );\n\n\t\txmlHttp.open( 'post', ajaxurl, true );\n\t\txmlHttp.onreadystatechange = function() {\n\t\t\tif ( xmlHttp.readyState > 3 && xmlHttp.status == 200 ) {\n\t\t\t\tresponse = xmlHttp.responseText;\n\t\t\t\ttry {\n\t\t\t\t\tresponse = JSON.parse( response );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t// The response may not be JSON, so just return it.\n\t\t\t\t}\n\t\t\t\tsuccess( response );\n\t\t\t}\n\t\t};\n\t\txmlHttp.setRequestHeader( 'X-Requested-With', 'XMLHttpRequest' );\n\t\txmlHttp.setRequestHeader( 'Content-type', 'application/x-www-form-urlencoded' );\n\t\txmlHttp.send( params );\n\t\treturn xmlHttp;\n\t}\n\n\tfunction fadeOut( element, success ) {\n\t\telement.classList.add( 'frm-fade' );\n\t\tsetTimeout( success, 1000 );\n\t}\n\n\tfunction invisible( classes ) {\n\t\tjQuery( classes ).css( 'visibility', 'hidden' );\n\t}\n\n\tfunction visible( classes ) {\n\t\tjQuery( classes ).css( 'visibility', 'visible' );\n\t}\n\n\tfunction initModal( id, width ) {\n\t\tconst upgradePopup = require( './upgrade-popup' );\n\t\treturn upgradePopup.initModal( id, width );\n\t}\n\n\tfunction toggle( cname, id ) {\n\t\tif ( id === '#' ) {\n\t\t\tconst cont = document.getElementById( cname );\n\t\t\tconst hidden = cont.style.display;\n\t\t\tif ( hidden === 'none' ) {\n\t\t\t\tcont.style.display = 'block';\n\t\t\t} else {\n\t\t\t\tcont.style.display = 'none';\n\t\t\t}\n\t\t} else {\n\t\t\tconst vis = cname.is( ':visible' );\n\t\t\tif ( vis ) {\n\t\t\t\tcname.hide();\n\t\t\t} else {\n\t\t\t\tcname.show();\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction removeWPUnload() {\n\t\twindow.onbeforeunload = null;\n\t\tconst w = jQuery( window );\n\t\tw.off( 'beforeunload.widgets' );\n\t\tw.off( 'beforeunload.edit-post' );\n\t}\n\n\tfunction addMultiselectLabelListener() {\n\t\tconst clickListener = e => {\n\t\t\tif ( 'LABEL' !== e.target.nodeName ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst labelFor = e.target.getAttribute( 'for' );\n\t\t\tif ( ! labelFor ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst input = document.getElementById( labelFor );\n\t\t\tif ( ! input || ! input.nextElementSibling ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst buttonToggle = input.nextElementSibling.querySelector( 'button.dropdown-toggle.multiselect' );\n\t\t\tif ( ! buttonToggle ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst triggerMultiselectClick = () => buttonToggle.click();\n\t\t\tsetTimeout( triggerMultiselectClick, 0 );\n\t\t};\n\t\tdocument.addEventListener( 'click', clickListener );\n\t}\n\n\tfunction maybeChangeEmbedFormMsg() {\n\t\tconst fieldId = jQuery( this ).closest( '.frm-single-settings' ).data( 'fid' );\n\t\tlet fieldItem = document.getElementById( 'frm_field_id_' + fieldId );\n\t\tif ( null === fieldItem || 'form' !== fieldItem.dataset.type ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfieldItem = jQuery( fieldItem );\n\n\t\tif ( this.options[ this.selectedIndex ].value ) {\n\t\t\tfieldItem.find( '.frm-not-set' )[ 0 ].classList.add( 'frm_hidden' );\n\t\t\tconst embedMsg = fieldItem.find( '.frm-embed-message' );\n\t\t\tembedMsg.html( embedMsg.data( 'embedmsg' ) + this.options[ this.selectedIndex ].text );\n\t\t\tfieldItem.find( '.frm-embed-field-placeholder' )[ 0 ].classList.remove( 'frm_hidden' );\n\t\t} else {\n\t\t\tfieldItem.find( '.frm-not-set' )[ 0 ].classList.remove( 'frm_hidden' );\n\t\t\tfieldItem.find( '.frm-embed-field-placeholder' )[ 0 ].classList.add( 'frm_hidden' );\n\t\t}\n\t}\n\n\tfunction toggleProductType() {\n\t\tconst settings = jQuery( this ).closest( '.frm-single-settings' ),\n\t\t\tcontainer = settings.find( '.frmjs_product_choices' ),\n\t\t\theading = settings.find( '.frm_prod_options_heading' ),\n\t\t\tcurrentVal = this.options[ this.selectedIndex ].value;\n\n\t\tcontainer.removeClass( 'frm_prod_type_single frm_prod_type_user_def' );\n\t\theading.removeClass( 'frm_prod_user_def' );\n\n\t\tif ( 'single' === currentVal ) {\n\t\t\tcontainer.addClass( 'frm_prod_type_single' );\n\t\t} else if ( 'user_def' === currentVal ) {\n\t\t\tcontainer.addClass( 'frm_prod_type_user_def' );\n\t\t\theading.addClass( 'frm_prod_user_def' );\n\t\t}\n\t}\n\n\t/**\n\t * @param {Number | string} fieldId\n\t * @return {boolean} True if the field is a product field.\n\t */\n\tfunction isProductField( fieldId ) {\n\t\tconst field = document.getElementById( 'frm_field_id_' + fieldId );\n\t\tif ( field === null ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn 'product' === field.getAttribute( 'data-type' );\n\t}\n\n\t/**\n\t * Serialize form data with vanilla JS.\n\t */\n\tfunction formToData( form ) {\n\t\tlet subKey, i,\n\t\t\tobject = {},\n\t\t\tformData = form.elements;\n\n\t\tfor ( i = 0; i < formData.length; i++ ) {\n\t\t\tlet input = formData[ i ],\n\t\t\t\tkey = input.name,\n\t\t\t\tvalue = input.value,\n\t\t\t\tnames = key.match( /(.*)\\[(.*)\\]/ );\n\n\t\t\tif ( ( input.type === 'radio' || input.type === 'checkbox' ) && ! input.checked ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( names !== null ) {\n\t\t\t\tkey = names[ 1 ];\n\t\t\t\tsubKey = names[ 2 ];\n\t\t\t\tif ( ! Reflect.has( object, key ) ) {\n\t\t\t\t\tobject[ key ] = {};\n\t\t\t\t}\n\t\t\t\tobject[ key ][ subKey ] = value;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Reflect.has in favor of: object.hasOwnProperty(key)\n\t\t\tif ( ! Reflect.has( object, key ) ) {\n\t\t\t\tobject[ key ] = value;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ( ! Array.isArray( object[ key ] ) ) {\n\t\t\t\tobject[ key ] = [ object[ key ] ];\n\t\t\t}\n\t\t\tobject[ key ].push( value );\n\t\t}\n\n\t\treturn object;\n\t}\n\n\t/**\n\t * Show, hide, and sort subfields of Name field on form builder.\n\t *\n\t * @since 4.11\n\t */\n\tfunction handleNameFieldOnFormBuilder() {\n\t\t/**\n\t\t * Gets subfield element from cache.\n\t\t *\n\t\t * @param {string} fieldId Field ID.\n\t\t * @param {string} key Cache key.\n\t\t * @return {HTMLElement|undefined} Return the element from cache or undefined if not found.\n\t\t */\n\t\tconst getSubFieldElFromCache = ( fieldId, key ) => {\n\t\t\twindow.frmCachedSubFields = window.frmCachedSubFields || {};\n\t\t\twindow.frmCachedSubFields[ fieldId ] = window.frmCachedSubFields[ fieldId ] || {};\n\t\t\treturn window.frmCachedSubFields[ fieldId ][ key ];\n\t\t};\n\n\t\t/**\n\t\t * Sets subfield element to cache.\n\t\t *\n\t\t * @param {string} fieldId Field ID.\n\t\t * @param {string} key Cache key.\n\t\t * @param {HTMLElement} el Element.\n\t\t */\n\t\tconst setSubFieldElToCache = ( fieldId, key, el ) => {\n\t\t\twindow.frmCachedSubFields = window.frmCachedSubFields || {};\n\t\t\twindow.frmCachedSubFields[ fieldId ] = window.frmCachedSubFields[ fieldId ] || {};\n\t\t\twindow.frmCachedSubFields[ fieldId ][ key ] = el;\n\t\t};\n\n\t\t/**\n\t\t * Gets column class from the number of columns.\n\t\t *\n\t\t * @param {Number} colCount Number of columns.\n\t\t * @return {string}\n\t\t */\n\t\tconst getColClass = colCount => 'frm' + parseInt( 12 / colCount );\n\n\t\tconst colClasses = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ].map( num => 'frm' + num );\n\n\t\tconst allSubFieldNames = [ 'first', 'middle', 'last' ];\n\n\t\t/**\n\t\t * Handles name layout change.\n\t\t *\n\t\t * @param {Event} event Event object.\n\t\t */\n\t\tconst onChangeLayout = event => {\n\t\t\tconst value = event.target.value;\n\t\t\tconst subFieldNames = value.split( '_' );\n\t\t\tconst fieldId = event.target.dataset.fieldId;\n\n\t\t\t/*\n\t\t\t * Live update form on the form builder.\n\t\t\t */\n\t\t\tconst container = document.querySelector( '#field_' + fieldId + '_inner_container .frm_combo_inputs_container' );\n\t\t\tconst newColClass = getColClass( subFieldNames.length );\n\n\t\t\t// Set all sub field elements to cache and hide all of them first.\n\t\t\tallSubFieldNames.forEach( name => {\n\t\t\t\tconst subFieldEl = container.querySelector( '[data-sub-field-name=\"' + name + '\"]' );\n\t\t\t\tif ( subFieldEl ) {\n\t\t\t\t\tsubFieldEl.classList.add( 'frm_hidden' );\n\t\t\t\t\tsubFieldEl.classList.remove( ...colClasses );\n\t\t\t\t\tsetSubFieldElToCache( fieldId, name, subFieldEl );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tsubFieldNames.forEach( subFieldName => {\n\t\t\t\tconst subFieldEl = getSubFieldElFromCache( fieldId, subFieldName );\n\t\t\t\tif ( ! subFieldEl ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsubFieldEl.classList.remove( 'frm_hidden' );\n\t\t\t\tsubFieldEl.classList.add( newColClass );\n\n\t\t\t\tcontainer.append( subFieldEl );\n\t\t\t} );\n\n\t\t\t/*\n\t\t\t * Live update subfield options.\n\t\t\t */\n\t\t\t// Hide all subfield options.\n\t\t\tallSubFieldNames.forEach( name => {\n\t\t\t\tconst optionsEl = document.querySelector( '.frm_sub_field_options-' + name + '[data-field-id=\"' + fieldId + '\"]' );\n\t\t\t\tif ( optionsEl ) {\n\t\t\t\t\toptionsEl.classList.add( 'frm_hidden' );\n\t\t\t\t\tsetSubFieldElToCache( fieldId, name + '_options', optionsEl );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tsubFieldNames.forEach( subFieldName => {\n\t\t\t\tconst optionsEl = getSubFieldElFromCache( fieldId, subFieldName + '_options' );\n\t\t\t\tif ( ! optionsEl ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\toptionsEl.classList.remove( 'frm_hidden' );\n\t\t\t} );\n\t\t};\n\n\t\tconst dropdownSelector = '.frm_name_layout_dropdown';\n\t\tdocument.addEventListener( 'change', event => {\n\t\t\tif ( event.target.matches( dropdownSelector ) ) {\n\t\t\t\tonChangeLayout( event );\n\t\t\t}\n\t\t}, false );\n\t}\n\n\tfunction debounce( func, wait = 100 ) {\n\t\treturn frmDom.util.debounce( func, wait );\n\t}\n\n\tfunction addSaveAndDragIconsToOption( fieldId, liObject ) {\n\t\tlet li, useTag, useTagHref;\n\t\tlet hasDragIcon = false;\n\t\tlet hasSaveIcon = false;\n\n\t\tif ( liObject.newOption ) {\n\t\t\tconst parser = new DOMParser();\n\t\t\tli = parser.parseFromString( liObject.newOption, 'text/html' ).body.childNodes[ 0 ];\n\t\t} else {\n\t\t\tli = liObject;\n\t\t}\n\n\t\tconst liIcons = li.querySelectorAll( 'svg' );\n\n\t\tliIcons.forEach( ( svg, key ) => {\n\t\t\tuseTag = svg.getElementsByTagNameNS( 'http://www.w3.org/2000/svg', 'use' )[ 0 ];\n\t\t\tif ( ! useTag ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tuseTagHref = useTag.getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ) || useTag.getAttribute( 'href' );\n\n\t\t\tif ( useTagHref === '#frm_drag_icon' ) {\n\t\t\t\thasDragIcon = true;\n\t\t\t}\n\n\t\t\tif ( useTagHref === '#frm_save_icon' ) {\n\t\t\t\thasSaveIcon = true;\n\t\t\t}\n\t\t} );\n\n\t\tif ( ! hasDragIcon ) {\n\t\t\tli.prepend( icons.drag.cloneNode( true ) );\n\t\t}\n\n\t\tif ( li.querySelector( `[id^=field_key_${ fieldId }-]` ) && ! hasSaveIcon ) {\n\t\t\tli.querySelector( `[id^=field_key_${ fieldId }-]` ).after( icons.save.cloneNode( true ) );\n\t\t}\n\n\t\tif ( liObject.newOption ) {\n\t\t\tliObject.newOption = li;\n\t\t}\n\t}\n\n\tfunction maybeAddSaveAndDragIcons( fieldId ) {\n\t\tconst fieldOptions = document.querySelectorAll( `[id^=frm_delete_field_${ fieldId }-]` );\n\t\t// return if there are no options.\n\t\tif ( fieldOptions.length < 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst options = [ ...fieldOptions ].slice( 1 );\n\t\toptions.forEach( ( li, _key ) => {\n\t\t\tif ( li.classList.contains( 'frm_other_option' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\taddSaveAndDragIconsToOption( fieldId, li );\n\t\t} );\n\t}\n\n\t/**\n\t * Enforce the maximum number of entries list columns dynamically.\n\t *\n\t * @since 6.24\n\t *\n\t * @return {void}\n\t */\n\tfunction maybeInitEntriesListPage() {\n\t\tif ( ! document.body.classList.contains( 'frm-admin-page-entries' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst screenOptionsWrapper = document.getElementById( 'screen-options-wrap' );\n\t\tif ( ! screenOptionsWrapper ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst maxSelectionsNote = div( {\n\t\t\tclassName: 'frm_warning_style',\n\t\t\ttext: __( 'Only 10 columns can be selected at a time.', 'formidable' ),\n\t\t} );\n\t\tmaxSelectionsNote.style.margin = 0;\n\n\t\tconst legend = screenOptionsWrapper.querySelector( 'legend' );\n\t\tlegend.parentNode.insertBefore( maxSelectionsNote, legend.nextElementSibling );\n\n\t\tconst checkboxes = Array.from( screenOptionsWrapper.querySelectorAll( 'input[type=\"checkbox\"]' ) );\n\t\tconst maximumColumns = 10;\n\t\tconst getSelectedCount = () => {\n\t\t\treturn checkboxes.reduce( ( count, checkbox ) => {\n\t\t\t\treturn checkbox.checked ? count + 1 : count;\n\t\t\t}, 0 );\n\t\t};\n\t\tconst disableCheckboxesIfAtMax = () => {\n\t\t\tif ( getSelectedCount() >= maximumColumns ) {\n\t\t\t\tmaxSelectionsNote.classList.remove( 'frm_hidden' );\n\t\t\t\tcheckboxes.forEach( checkbox => {\n\t\t\t\t\tif ( ! checkbox.checked ) {\n\t\t\t\t\t\tcheckbox.parentNode.classList.add( 'frm_noallow' );\n\t\t\t\t\t\tcheckbox.disabled = true;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tmaxSelectionsNote.classList.add( 'frm_hidden' );\n\t\t\t}\n\t\t};\n\t\tconst addCheckboxListeners = () => {\n\t\t\tcheckboxes.forEach(\n\t\t\t\tcheckbox => {\n\t\t\t\t\tcheckbox.addEventListener(\n\t\t\t\t\t\t'change',\n\t\t\t\t\t\tevent => {\n\t\t\t\t\t\t\tif ( event.target.checked ) {\n\t\t\t\t\t\t\t\tdisableCheckboxesIfAtMax();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tmaxSelectionsNote.classList.add( 'frm_hidden' );\n\n\t\t\t\t\t\t\t\t// Enable all checkboxes when a checkbox is unchecked.\n\t\t\t\t\t\t\t\tcheckboxes.forEach(\n\t\t\t\t\t\t\t\t\tcheckbox => {\n\t\t\t\t\t\t\t\t\t\tcheckbox.parentNode.classList.remove( 'frm_noallow' );\n\t\t\t\t\t\t\t\t\t\tcheckbox.disabled = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\t};\n\n\t\tdisableCheckboxesIfAtMax();\n\t\taddCheckboxListeners();\n\t}\n\n\tfunction initOnSubmitAction() {\n\t\tconst onChangeType = event => {\n\t\t\tif ( ! event.target.checked ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst actionEl = event.target.closest( '.frm_form_action_settings' );\n\t\t\tactionEl.querySelectorAll( '.frm_on_submit_dependent_setting:not(.frm_hidden)' ).forEach( el => {\n\t\t\t\tel.classList.add( 'frm_hidden' );\n\t\t\t} );\n\n\t\t\tconst activeEls = actionEl.querySelectorAll( '.frm_on_submit_dependent_setting[data-show-if-' + event.target.value + ']' );\n\t\t\tactiveEls.forEach( activeEl => {\n\t\t\t\tactiveEl.classList.remove( 'frm_hidden' );\n\t\t\t} );\n\n\t\t\tactionEl.setAttribute( 'data-on-submit-type', event.target.value );\n\t\t};\n\n\t\tfrmDom.util.documentOn( 'change', '.frm_on_submit_type input[type=\"radio\"]', onChangeType );\n\t}\n\n\t/**\n\t * Listen for click events for an API-loaded email collection form.\n\t *\n\t * This is used for the Active Campaign sign-up form in the inbox page (when there are no messages).\n\t */\n\tfunction initAddMyEmailAddress() {\n\t\tjQuery( document ).on(\n\t\t\t'click',\n\t\t\t'#frm-add-my-email-address',\n\t\t\tevent => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\taddMyEmailAddress();\n\t\t\t}\n\t\t);\n\n\t\tconst emptyInbox = document.getElementById( 'frm_empty_inbox' );\n\t\tconst leaveEmailInput = document.getElementById( 'frm_leave_email' );\n\n\t\tif ( emptyInbox && leaveEmailInput ) {\n\t\t\tconst leaveEmailModal = document.getElementById( 'frm-leave-email-modal' );\n\t\t\tleaveEmailModal.classList.remove( 'frm_hidden' );\n\t\t\tleaveEmailModal.querySelector( '.frm_modal_footer' ).classList.add( 'frm_hidden' );\n\n\t\t\tleaveEmailInput.addEventListener(\n\t\t\t\t'keyup',\n\t\t\t\tevent => {\n\t\t\t\t\tif ( 'Enter' === event.key ) {\n\t\t\t\t\t\tconst button = document.getElementById( 'frm-add-my-email-address' );\n\t\t\t\t\t\tif ( button ) {\n\t\t\t\t\t\t\tbutton.click();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t}\n\n\tfunction addMyEmailAddress() {\n\t\tconst email = document.getElementById( 'frm_leave_email' ).value.trim();\n\t\tif ( '' === email ) {\n\t\t\thandleEmailAddressError( 'empty' );\n\t\t\treturn;\n\t\t}\n\n\t\tconst regex = /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/i;\n\t\tif ( regex.test( email ) === false ) {\n\t\t\thandleEmailAddressError( 'invalid' );\n\t\t\treturn;\n\t\t}\n\n\t\tconst $hiddenForm = jQuery( '#frmapi-email-form' ).find( 'form' );\n\t\tconst $hiddenEmailField = $hiddenForm.find( '[type=\"email\"]' ).not( '.frm_verify' );\n\t\tif ( ! $hiddenEmailField.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst emptyInbox = document.getElementById( 'frm_empty_inbox' );\n\t\tif ( emptyInbox ) {\n\t\t\tdocument.getElementById( 'frm-add-my-email-address' ).remove();\n\n\t\t\tconst emailWrapper = document.getElementById( 'frm_leave_email_wrapper' );\n\t\t\tif ( emailWrapper ) {\n\t\t\t\temailWrapper.classList.add( 'frm_hidden' );\n\t\t\t\tconst spinner = span( { className: 'frm-wait frm_spinner' } );\n\t\t\t\tspinner.style.visibility = 'visible';\n\t\t\t\tspinner.style.float = 'none';\n\t\t\t\tspinner.style.width = 'unset';\n\t\t\t\temailWrapper.parentElement.insertBefore(\n\t\t\t\t\tspinner,\n\t\t\t\t\temailWrapper.nextElementSibling\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t$hiddenEmailField.val( email );\n\t\tjQuery.ajax( {\n\t\t\ttype: 'POST',\n\t\t\turl: $hiddenForm.attr( 'action' ),\n\t\t\tdata: $hiddenForm.serialize() + '&action=frm_forms_preview'\n\t\t} ).done( function( data ) {\n\t\t\tconst message = jQuery( data ).find( '.frm_message' ).text().trim();\n\t\t\tif ( message.indexOf( 'Thanks!' ) === -1 ) {\n\t\t\t\thandleEmailAddressError( 'invalid' );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst apiForm = document.getElementById( 'frmapi-email-form' );\n\t\t\tconst spinner = apiForm.parentElement.querySelector( '.frm_spinner' );\n\t\t\tif ( spinner ) {\n\t\t\t\tspinner.remove();\n\t\t\t}\n\n\t\t\tconst showSuccessMessage = wp.hooks.applyFilters( 'frm_thank_you_on_signup', true );\n\t\t\tif ( showSuccessMessage ) {\n\t\t\t\t// Handle successful form submission.\n\t\t\t\t// handle the Active Campaign form on the inbox page.\n\t\t\t\tdocument.getElementById( 'frm_leave_email_wrapper' ).replaceWith(\n\t\t\t\t\tspan( __( 'Thank you for signing up!', 'formidable' ) )\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Adds footer links to the admin body content.\n\t *\n\t * @return {void}\n\t */\n\tfunction addAdminFooterLinks() {\n\t\tconst footerLinks = document.querySelector( '.frm-admin-footer-links' );\n\t\tconst container = document.querySelector( '.frm_page_container' ) ?? document.getElementById( 'wpbody-content' );\n\n\t\tif ( ! footerLinks || ! container ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer.appendChild( footerLinks );\n\t\tfooterLinks.classList.remove( 'frm_hidden' );\n\t}\n\n\t/**\n\t * Apply zebra striping to a table while ignoring empty rows.\n\t *\n\t * @param {string} tableSelector The CSS selector for the table.\n\t * @param {string} emptyRowClass The class name used to identify empty rows.\n\t */\n\tfunction applyZebraStriping( tableSelector, emptyRowClass ) {\n\t\t// Get all non-empty table rows within the specified table\n\t\tconst rows = document.querySelectorAll( `${ tableSelector } tr${ emptyRowClass ? `:not(.${ emptyRowClass })` : '' }` );\n\t\tif ( rows.length < 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet isOdd = true;\n\t\trows.forEach( row => {\n\t\t\t// Clean old \"frm-odd\" or \"frm-even\" classes and add the appropriate new class\n\t\t\trow.classList.remove( 'frm-odd', 'frm-even' );\n\t\t\trow.classList.add( isOdd ? 'frm-odd' : 'frm-even' );\n\n\t\t\tisOdd = ! isOdd;\n\t\t} );\n\n\t\tconst tables = document.querySelectorAll( tableSelector );\n\t\ttables.forEach( table => table.classList.add( 'frm-zebra-striping' ) );\n\t}\n\n\tfunction maybeHideShortcodes( e ) {\n\t\tif ( ! builderPage ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\tif ( e.target.classList.contains( 'frm-show-box' ) || ( e.target.parentElement && e.target.parentElement.classList.contains( 'frm-show-box' ) ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst sidebar = document.getElementById( 'frm_adv_info' );\n\t\tif ( ! sidebar ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( sidebar.dataset.fills === e.target.id && typeof e.target.id !== 'undefined' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isChild = e.target.closest( '#frm_adv_info' );\n\n\t\tif ( ! isChild && sidebar.style.display !== 'none' ) {\n\t\t\thideShortcodes( sidebar );\n\t\t}\n\t}\n\n\t/**\n\t * Initializes and manages the visibility of dependent elements based on the selected options in dropdowns with the 'frm_select_with_dependency' class.\n\t * It sets up initial visibility at page load and updates it on each dropdown change.\n\t *\n\t * @since 6.9\n\t *\n\t * @return {void}\n\t */\n\tfunction initSelectDependencies() {\n\t\tconst selects = document.querySelectorAll( 'select.frm_select_with_dependency' );\n\n\t\t/**\n\t\t * Toggles the visibility of dependent elements associated with a select element based on its current selection.\n\t\t *\n\t\t * @since 6.9\n\t\t *\n\t\t * @param {HTMLElement} select The select element whose dependencies need to be managed.\n\t\t * @return {void}\n\t\t */\n\t\tfunction toggleDependencyVisibility( select ) {\n\t\t\tconst selectedOption = select.options[ select.selectedIndex ];\n\t\t\tselect.querySelectorAll( 'option[data-dependency]:not([data-dependency-skip])' ).forEach( option => {\n\t\t\t\tconst dependencyElement = document.querySelector( option.dataset.dependency );\n\t\t\t\tdependencyElement?.classList.toggle( 'frm_hidden', selectedOption !== option );\n\t\t\t} );\n\t\t}\n\n\t\t// Initial setup: Show dependencies based on the current selection in each dropdown\n\t\tselects.forEach( toggleDependencyVisibility );\n\n\t\t// Update dependencies visibility on dropdown change\n\t\tfrmDom.util.documentOn( 'change', 'select.frm_select_with_dependency', event => toggleDependencyVisibility( event.target ) );\n\t}\n\n\t/**\n\t * Moves the focus to the next single option input field in the list and positions the cursor at the end of the text.\n\t *\n\t * @param {HTMLElement} currentInput The currently focused input element.\n\t */\n\tfunction focusNextSingleOptionInput( currentInput ) {\n\t\tconst optionsList = currentInput.closest( '.frm_single_option' ).parentElement;\n\t\tconst inputs = optionsList.querySelectorAll( '.frm_single_option input[name^=\"field_options[\" ], .frm_single_option input[name^=\"rows_\"]' );\n\t\tconst inputsArray = Array.from( inputs );\n\n\t\t// Find the index of the currently focused input\n\t\tconst currentIndex = inputsArray.indexOf( currentInput );\n\n\t\tif ( currentIndex < 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Find the next visible input field\n\t\tconst nextInput = inputsArray.slice( currentIndex + 1 ).find( input => input.offsetParent !== null );\n\n\t\tif ( nextInput ) {\n\t\t\tnextInput.focus();\n\n\t\t\t// Move the cursor to the end of the text in the next input field\n\t\t\tconst textLength = nextInput.value.length;\n\t\t\tnextInput.setSelectionRange( textLength, textLength );\n\t\t}\n\t}\n\n\treturn {\n\t\tinit: function() {\n\t\t\tinitAddMyEmailAddress();\n\t\t\taddAdminFooterLinks();\n\n\t\t\ts = {};\n\n\t\t\t// Bootstrap dropdown button\n\t\t\tjQuery( '.wp-admin' ).on( 'click', function( e ) {\n\t\t\t\tconst t = jQuery( e.target );\n\t\t\t\tconst $openDrop = jQuery( '.dropdown.open' );\n\t\t\t\tif ( $openDrop.length && ! t.hasClass( 'dropdown' ) && ! t.closest( '.dropdown' ).length ) {\n\t\t\t\t\t$openDrop.removeClass( 'open' );\n\t\t\t\t}\n\t\t\t} );\n\t\t\tjQuery( '#frm_bs_dropdown:not(.open) a' ).on( 'click', focusSearchBox );\n\n\t\t\tif ( typeof thisFormId === 'undefined' ) {\n\t\t\t\tthisFormId = jQuery( document.getElementById( 'form_id' ) ).val();\n\t\t\t}\n\n\t\t\t// Add event listener for dismissible warning messages.\n\t\t\tdocument.querySelectorAll( '.frm-warning-dismiss' ).forEach( dismissIcon => {\n\t\t\t\tonClickPreventDefault( dismissIcon, dismissWarningMessage );\n\t\t\t} );\n\n\t\t\tfrmAdminBuild.inboxBannerInit();\n\n\t\t\tif ( $newFields.length > 0 ) {\n\t\t\t\t// only load this on the form builder page\n\t\t\t\tfrmAdminBuild.buildInit();\n\t\t\t} else if ( document.getElementById( 'frm_notification_settings' ) !== null ) {\n\t\t\t\t// only load on form settings page\n\t\t\t\tfrmAdminBuild.settingsInit();\n\t\t\t} else if ( document.getElementById( 'frm_styling_form' ) !== null ) {\n\t\t\t\t// load styling settings js\n\t\t\t\tfrmAdminBuild.styleInit();\n\t\t\t} else if ( document.getElementById( 'form_global_settings' ) !== null ) {\n\t\t\t\t// global settings page\n\t\t\t\tfrmAdminBuild.globalSettingsInit();\n\t\t\t} else if ( document.getElementById( 'frm_export_xml' ) !== null ) {\n\t\t\t\t// import/export page\n\t\t\t\tfrmAdminBuild.exportInit();\n\t\t\t} else if ( null !== document.querySelector( '.frm-inbox-wrapper' ) ) {\n\t\t\t\t// Dashboard page inbox.\n\t\t\t\tfrmAdminBuild.inboxInit();\n\t\t\t} else if ( document.getElementById( 'frm-welcome' ) !== null ) {\n\t\t\t\t// Solution install page\n\t\t\t\tfrmAdminBuild.solutionInit();\n\t\t\t} else {\n\t\t\t\tmaybeInitEntriesListPage();\n\n\t\t\t\tinitAutocomplete();\n\n\t\t\t\tjQuery( '[data-frmprint]' ).on( 'click', function() {\n\t\t\t\t\twindow.print();\n\t\t\t\t\treturn false;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tjQuery( document ).on( 'change', 'select[data-toggleclass], input[data-toggleclass]', toggleFormOpts );\n\t\t\tinitSelectDependencies();\n\n\t\t\tconst $advInfo = jQuery( document.getElementById( 'frm_adv_info' ) );\n\t\t\tif ( $advInfo.length > 0 || jQuery( '.frm_field_list' ).length > 0 ) {\n\t\t\t\t// only load on the form, form settings, and view settings pages\n\t\t\t\tfrmAdminBuild.panelInit();\n\t\t\t}\n\n\t\t\tloadTooltips();\n\t\t\tinitUpgradeModal();\n\t\t\tfrmDom.util.documentOn( 'click', '[data-modal-title]', showBasicModal );\n\n\t\t\t// used on build, form settings, and view settings\n\t\t\tconst $shortCodeDiv = jQuery( document.getElementById( 'frm_shortcodediv' ) );\n\t\t\tif ( $shortCodeDiv.length > 0 ) {\n\t\t\t\tjQuery( 'a.edit-frm_shortcode' ).on( 'click', function() {\n\t\t\t\t\tif ( $shortCodeDiv.is( ':hidden' ) ) {\n\t\t\t\t\t\t$shortCodeDiv.slideDown( 'fast' );\n\t\t\t\t\t\tthis.style.display = 'none';\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t} );\n\n\t\t\t\tjQuery( '.cancel-frm_shortcode', '#frm_shortcodediv' ).on( 'click', function() {\n\t\t\t\t\t$shortCodeDiv.slideUp( 'fast' );\n\t\t\t\t\t$shortCodeDiv.siblings( 'a.edit-frm_shortcode' ).show();\n\t\t\t\t\treturn false;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// tabs\n\t\t\tjQuery( document ).on( 'click', '#frm-nav-tabs a', clickNewTab );\n\t\t\tjQuery( '.post-type-frm_display .frm-nav-tabs a, .frm-category-tabs a' ).on( 'click', function() {\n\t\t\t\tconst showUpgradeTab = this.classList.contains( 'frm_show_upgrade_tab' );\n\t\t\t\tif ( this.classList.contains( 'frm_noallow' ) && ! showUpgradeTab ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( showUpgradeTab ) {\n\t\t\t\t\tpopulateUpgradeTab( this );\n\t\t\t\t}\n\n\t\t\t\tclickTab( this );\n\t\t\t\treturn false;\n\t\t\t} );\n\t\t\tclickTab( jQuery( '.starttab a' ), 'auto' );\n\n\t\t\t// submit the search form with dropdown\n\t\t\tjQuery( document ).on( 'click', '#frm-fid-search-menu a', function() {\n\t\t\t\tconst val = this.id.replace( 'fid-', '' );\n\t\t\t\tjQuery( 'select[name=\"fid\"]' ).val( val );\n\t\t\t\ttriggerSubmit( document.getElementById( 'posts-filter' ) );\n\t\t\t\treturn false;\n\t\t\t} );\n\n\t\t\tjQuery( '.frm_select_box' ).on( 'click focus', function() {\n\t\t\t\tthis.select();\n\t\t\t} );\n\n\t\t\tjQuery( document ).on( 'input search change', '.frm-auto-search:not(#frm-form-templates-page #template-search-input)', searchContent );\n\t\t\tjQuery( document ).on( 'focusin click', '.frm-auto-search', stopPropagation );\n\t\t\tconst autoSearch = jQuery( '.frm-auto-search' );\n\t\t\tif ( autoSearch.val() !== '' ) {\n\t\t\t\tautoSearch.trigger( 'keyup' );\n\t\t\t}\n\n\t\t\t// Initialize Formidable Connection.\n\t\t\tFrmFormsConnect.init();\n\n\t\t\tjQuery( document ).on( 'click', '.frm-install-addon', installAddon );\n\t\t\tjQuery( document ).on( 'click', '.frm-activate-addon', activateAddon );\n\t\t\tjQuery( document ).on( 'click', '.frm-solution-multiple', installMultipleAddons );\n\n\t\t\t// prevent annoying confirmation message from WordPress\n\t\t\tjQuery( 'button, input[type=submit]' ).on( 'click', removeWPUnload );\n\n\t\t\taddMultiselectLabelListener();\n\n\t\t\tfrmAdminBuild.hooks.addFilter(\n\t\t\t\t'frm_before_embed_modal',\n\t\t\t\t( ids, { element, type } ) => {\n\t\t\t\t\tif ( 'form' !== type ) {\n\t\t\t\t\t\treturn ids;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet formId, formKey;\n\t\t\t\t\tconst row = element.closest( 'tr' );\n\n\t\t\t\t\tif ( row ) {\n\t\t\t\t\t\t// Embed icon on form index.\n\t\t\t\t\t\tformId = parseInt( row.querySelector( '.column-id' ).textContent );\n\t\t\t\t\t\tformKey = row.querySelector( '.column-form_key' ).textContent;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Embed button in form builder / form settings.\n\t\t\t\t\t\tformId = document.getElementById( 'form_id' ).value;\n\n\t\t\t\t\t\tconst formKeyInput = document.getElementById( 'frm_form_key' );\n\t\t\t\t\t\tif ( formKeyInput ) {\n\t\t\t\t\t\t\tformKey = formKeyInput.value;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst previewDrop = document.getElementById( 'frm-previewDrop' );\n\t\t\t\t\t\t\tif ( previewDrop ) {\n\t\t\t\t\t\t\t\tformKey = previewDrop.nextElementSibling.querySelector( '.dropdown-item a' ).getAttribute( 'href' ).split( 'form=' )[ 1 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [ formId, formKey ];\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tdocument.querySelectorAll( '#frm-show-fields > li, .frm_grid_container li' ).forEach( ( el, _key ) => {\n\t\t\t\tel.addEventListener( 'click', function() {\n\t\t\t\t\tconst fieldId = this.querySelector( 'li' )?.dataset.fid || this.dataset.fid;\n\t\t\t\t\tmaybeAddSaveAndDragIcons( fieldId );\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\tconst smallScreenProceedButton = document.getElementById( 'frm_small_screen_proceed_button' );\n\t\t\tif ( smallScreenProceedButton ) {\n\t\t\t\tonClickPreventDefault( smallScreenProceedButton, () => {\n\t\t\t\t\tdocument.getElementById( 'frm_small_device_message_container' )?.remove();\n\t\t\t\t\tdoJsonPost( 'small_screen_proceed', new FormData() );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tconst saleBanner = document.getElementById( 'frm_sale_banner' );\n\t\t\tconst saleDismiss = saleBanner?.querySelector( '.dismiss' );\n\t\t\tif ( saleBanner ) {\n\t\t\t\tonClickPreventDefault( saleBanner, event => {\n\t\t\t\t\tconst target = event.target;\n\t\t\t\t\tif ( target.closest( '.dismiss' ) ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\twindow.location.href = saleBanner.getAttribute( 'data-url' );\n\t\t\t\t} );\n\n\t\t\t\tif ( saleDismiss ) {\n\t\t\t\t\tonClickPreventDefault( saleDismiss, () => {\n\t\t\t\t\t\tsaleBanner.remove();\n\n\t\t\t\t\t\tconst formData = new FormData();\n\t\t\t\t\t\tdoJsonPost( 'sale_banner_dismiss', formData );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tbuildInit: function() {\n\t\t\tjQuery( '#frm_builder_page' ).on( 'mouseup', '*:not(.frm-show-box)', maybeHideShortcodes );\n\n\t\t\tlet loadFieldId, $builderForm, builderArea;\n\n\t\t\tdebouncedSyncAfterDragAndDrop = debounce( syncAfterDragAndDrop, 10 );\n\t\t\tpostBodyContent = document.getElementById( 'post-body-content' );\n\t\t\t$postBodyContent = jQuery( postBodyContent );\n\n\t\t\tif ( jQuery( '.frm_field_loading' ).length ) {\n\t\t\t\tloadFieldId = jQuery( '.frm_field_loading' ).first().attr( 'id' );\n\t\t\t\tloadFields( loadFieldId );\n\t\t\t}\n\n\t\t\tsetupSortable( 'ul.frm_sorting' );\n\n\t\t\tdocument.querySelectorAll( '.field_type_list > li:not(.frm_show_upgrade)' ).forEach( makeDraggable );\n\n\t\t\tjQuery( 'ul.field_type_list, .field_type_list li, ul.frm_code_list, .frm_code_list li, .frm_code_list li a, #frm_adv_info #category-tabs li, #frm_adv_info #category-tabs li a' ).disableSelection();\n\n\t\t\tjQuery( '.frm_submit_ajax' ).on( 'click', submitBuild );\n\t\t\tjQuery( '.frm_submit_no_ajax' ).on( 'click', submitNoAjax );\n\n\t\t\taddFormNameModalEvents();\n\n\t\t\tjQuery( 'a.edit-form-status' ).on( 'click', slideDown );\n\t\t\tjQuery( '.cancel-form-status' ).on( 'click', slideUp );\n\t\t\tjQuery( '.save-form-status' ).on( 'click', function() {\n\t\t\t\tconst newStatus = jQuery( document.getElementById( 'form_change_status' ) ).val();\n\t\t\t\tjQuery( 'input[name=\"new_status\"]' ).val( newStatus );\n\t\t\t\tjQuery( document.getElementById( 'form-status-display' ) ).html( newStatus );\n\t\t\t\tjQuery( '.cancel-form-status' ).trigger( 'click' );\n\t\t\t\treturn false;\n\t\t\t} );\n\n\t\t\tjQuery( '.frm_form_builder form' ).first().on( 'submit', function() {\n\t\t\t\tjQuery( '.inplace_field' ).trigger( 'blur' );\n\t\t\t} );\n\n\t\t\tinitiateMultiselect();\n\t\t\trenumberPageBreaks();\n\n\t\t\t$builderForm = jQuery( builderForm );\n\t\t\tbuilderArea = document.getElementById( 'frm_form_editor_container' );\n\t\t\t$builderForm.on( 'click', '.frm_add_logic_row', addFieldLogicRow );\n\t\t\t$builderForm.on( 'click', '.frm_add_watch_lookup_row', addWatchLookupRow );\n\t\t\t$builderForm.on( 'change', '.frm_get_values_form', updateGetValueFieldSelection );\n\t\t\t$builderForm.on( 'change', '.frm_logic_field_opts', getFieldValues );\n\t\t\t$builderForm.on( 'frm-multiselect-changed', 'select[name^=\"field_options[admin_only_\"]', adjustVisibilityValuesForEveryoneValues );\n\n\t\t\tjQuery( document.getElementById( 'frm-insert-fields' ) ).on( 'click', '.frm_add_field', addFieldClick );\n\t\t\t$newFields.on( 'click', '.frm_clone_field', duplicateField );\n\t\t\t$builderForm.on( 'blur', 'input[id^=\"frm_calc\"]', checkCalculationCreatedByUser );\n\t\t\t$builderForm.on( 'change', 'input.frm_format_opt, input.frm_max_length_opt', toggleInvalidMsg );\n\t\t\t$builderForm.on( 'change click', '[data-changeme]', liveChanges );\n\t\t\t$builderForm.on( 'click', 'input.frm_req_field', markRequired );\n\t\t\t$builderForm.on( 'click', '.frm_mark_unique', markUnique );\n\n\t\t\t$builderForm.on( 'change', '.frm_repeat_format', toggleRepeatButtons );\n\t\t\t$builderForm.on( 'change', '.frm_repeat_limit', checkRepeatLimit );\n\t\t\t$builderForm.on( 'change', '.frm_js_checkbox_limit', checkCheckboxSelectionsLimit );\n\t\t\t$builderForm.on( 'input', 'input[name^=\"field_options[add_label_\"]', function() {\n\t\t\t\tupdateRepeatText( this, 'add' );\n\t\t\t} );\n\t\t\t$builderForm.on( 'input', 'input[name^=\"field_options[remove_label_\"]', function() {\n\t\t\t\tupdateRepeatText( this, 'remove' );\n\t\t\t} );\n\t\t\t$builderForm.on( 'change', 'select[name^=\"field_options[data_type_\"]', maybeClearWatchFields );\n\t\t\tjQuery( builderArea ).on( 'click', '.frm-collapse-page', maybeCollapsePage );\n\t\t\tjQuery( builderArea ).on( 'click', '.frm-collapse-section', maybeCollapseSection );\n\t\t\t$builderForm.on( 'click', '.frm-single-settings h3, .frm-single-settings h4.frm-collapsible', maybeCollapseSettings );\n\t\t\t$builderForm.on( 'keydown', '.frm-single-settings h3, .frm-single-settings h4.frm-collapsible', function( event ) {\n\t\t\t\t// If so, only proceed if the key pressed was 'Enter' or 'Space'\n\t\t\t\tif ( event.key === 'Enter' || event.key === ' ' ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tmaybeCollapseSettings.call( this, event );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tjQuery( builderArea ).on( 'show.bs.dropdown hide.bs.dropdown', changeSectionStyle );\n\n\t\t\t$builderForm.on( 'click', '.frm_toggle_sep_values', toggleSepValues );\n\t\t\t$builderForm.on( 'click', '.frm_toggle_image_options', toggleImageOptions );\n\t\t\t$builderForm.on( 'click', '.frm_remove_image_option', removeImageFromOption );\n\t\t\t$builderForm.on( 'click', '.frm_choose_image_box', addImageToOption );\n\t\t\t$builderForm.on( 'change', '.frm_hide_image_text', refreshOptionDisplay );\n\t\t\t$builderForm.on( 'change', '.frm_field_options_image_size', setImageSize );\n\t\t\t$builderForm.on( 'click', '.frm_multiselect_opt', toggleMultiselect );\n\t\t\t$newFields.on( 'mousedown', 'input, textarea, select', stopFieldFocus );\n\t\t\t$newFields.on( 'click', 'input[type=radio], input[type=checkbox]', stopFieldFocus );\n\t\t\t$newFields.on( 'click', '.frm_delete_field', clickDeleteField );\n\t\t\t$newFields.on( 'click', '.frm_select_field', clickSelectField );\n\t\t\tjQuery( document ).on( 'click', '.frm_delete_field_group', clickDeleteFieldGroup );\n\t\t\tjQuery( document ).on( 'click', '.frm_clone_field_group', duplicateFieldGroup );\n\t\t\tjQuery( document ).on( 'click', '#frm_field_group_controls > span:first-child', clickFieldGroupLayout );\n\t\t\tjQuery( document ).on( 'click', '.frm-row-layout-option', handleFieldGroupLayoutOptionClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-merge-fields-into-row .frm-row-layout-option', handleFieldGroupLayoutOptionInsideMergeClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-custom-field-group-layout', customFieldGroupLayoutClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-merge-fields-into-row .frm-custom-field-group-layout', customFieldGroupLayoutInsideMergeClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-break-field-group', breakFieldGroupClick );\n\t\t\t$newFields.on( 'click', '#frm_field_group_popup .frm_grid_container input', focusFieldGroupInputOnClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-cancel-custom-field-group-layout', cancelCustomFieldGroupClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-save-custom-field-group-layout', saveCustomFieldGroupClick );\n\t\t\t$newFields.on( 'click', 'ul.frm_sorting', fieldGroupClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-merge-fields-into-row', mergeFieldsIntoRowClick );\n\t\t\tjQuery( document ).on( 'click', '.frm-delete-field-groups', deleteFieldGroupsClick );\n\t\t\t$newFields.on( 'click', '.frm-field-action-icons [data-toggle=\"dropdown\"]', function() {\n\t\t\t\tthis.closest( 'li.form-field' ).classList.add( 'frm-field-settings-open' );\n\t\t\t\tjQuery( document ).on( 'click', '#frm_builder_page', handleClickOutsideOfFieldSettings );\n\t\t\t} );\n\t\t\t$newFields.on( 'mousemove', 'ul.frm_sorting', checkForMultiselectKeysOnMouseMove );\n\t\t\t$newFields.on( 'show.bs.dropdown', '.frm-field-action-icons', onFieldActionDropdownShow );\n\t\t\tjQuery( document ).on( 'show.bs.dropdown', '#frm_field_group_controls', onFieldGroupActionDropdownShow );\n\t\t\t$builderForm.on( 'click', '.frm_single_option a[data-removeid]', deleteFieldOption );\n\t\t\t$builderForm.on( 'mousedown', '.frm_single_option input[type=radio]', maybeUncheckRadio );\n\t\t\t$builderForm.on( 'focusin', '.frm_single_option input[type=text]', maybeClearOptText );\n\t\t\t$builderForm.on( 'click', '.frm_add_opt', addFieldOption );\n\t\t\t$builderForm.on( 'change', '.frm_single_option input', resetOptOnChange );\n\t\t\t$builderForm.on( 'change', '.frm_image_id', resetOptOnChange );\n\t\t\t$builderForm.on( 'change', '.frm_toggle_mult_sel', toggleMultSel );\n\n\t\t\t$newFields.on( 'click', '.frm_primary_label', clickLabel );\n\t\t\t$newFields.on( 'click', '.frm_description', clickDescription );\n\t\t\t$newFields.on( 'click', 'li.ui-state-default:not(.frm_noallow)', clickVis );\n\t\t\t$newFields.on( 'dblclick', 'li.ui-state-default', openAdvanced );\n\t\t\t$builderForm.on( 'change', '.frm_tax_form_select', toggleFormTax );\n\t\t\t$builderForm.on( 'change', 'select.conf_field', addConf );\n\n\t\t\t$builderForm.on( 'change', '.frm_get_field_selection', getFieldSelection );\n\n\t\t\t$builderForm.on( 'click', '.frm-show-inline-modal', maybeShowInlineModal );\n\t\t\t$builderForm.on( 'keydown', '.frm-show-inline-modal', function( event ) {\n\t\t\t\tconst { key } = event;\n\t\t\t\tif ( key === 'Enter' || key === ' ' ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tmaybeShowInlineModal.call( this, event );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t$builderForm.on( 'click', '.frm-inline-modal .dismiss', dismissInlineModal );\n\t\t\tjQuery( document ).on( 'change', '[data-frmchange]', changeInputtedValue );\n\n\t\t\tdocument.addEventListener( 'click', closeModalOnOutsideClick );\n\n\t\t\t$builderForm.on( 'change', '.frm_include_extras_field', rePopCalcFieldsForSummary );\n\t\t\t$builderForm.on( 'change', 'select[name^=\"field_options[form_select_\"]', maybeChangeEmbedFormMsg );\n\n\t\t\tjQuery( document ).on( 'submit', '#frm_js_build_form', buildSubmittedNoAjax );\n\t\t\tjQuery( document ).on( 'change', '#frm_builder_page input:not(.frm-search-input):not(.frm-custom-grid-size-input), #frm_builder_page select, #frm_builder_page textarea', fieldUpdated );\n\n\t\t\tpopAllProductFields();\n\n\t\t\tjQuery( document ).on( 'change', '.frmjs_prod_data_type_opt', toggleProductType );\n\n\t\t\tjQuery( document ).on( 'focus', '.frm-single-settings ul input[type=\"text\"][name^=\"field_options[options_\"]', onOptionTextFocus );\n\t\t\tjQuery( document ).on( 'blur', '.frm-single-settings ul input[type=\"text\"][name^=\"field_options[options_\"]', onOptionTextBlur );\n\n\t\t\tfrmDom.util.documentOn( 'click', '.frm-show-field-settings', clickVis );\n\t\t\tfrmDom.util.documentOn( 'change', 'select.frm_format_dropdown, select.frm_phone_type_dropdown', maybeUpdateFormatInput );\n\n\t\t\t// Navigate to the next input field on pressing Enter in a single option field\n\t\t\t$builderForm.on( 'keydown', '.frm_single_option input[name^=\"field_options[\"], .frm_single_option input[name^=\"rows_\"]', event => {\n\t\t\t\tif ( 'Enter' === event.key ) {\n\t\t\t\t\tfocusNextSingleOptionInput( event.currentTarget );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tinitBulkOptionsOverlay();\n\t\t\thideEmptyEle();\n\t\t\tdocument.addEventListener( 'frm_added_field', hideEmptyEle );\n\t\t\tmaybeHideQuantityProductFieldOption();\n\t\t\thandleNameFieldOnFormBuilder();\n\t\t\ttoggleSectionHolder();\n\t\t\thandleShowPasswordLiveUpdate();\n\t\t\tdocument.addEventListener( 'scroll', updateShortcodesPopupPosition, true );\n\t\t\tdocument.addEventListener( 'change', handleBuilderChangeEvent );\n\t\t\tdocument.querySelector( '.frm_form_builder' ).addEventListener( 'mousedown', event => {\n\t\t\t\tif ( event.shiftKey ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t} );\n\t\t\twp.hooks.addAction( 'frmShowedFieldSettings', 'formidableAdmin', ( showBtn, fieldSettingsEl ) => {\n\t\t\t\tfieldSettingsEl.querySelectorAll( '.frm-collapse-me' ).forEach( addSlideAnimationCssVars );\n\t\t\t}, 9999 );\n\t\t},\n\n\t\tsettingsInit: function() {\n\t\t\tconst $formActions = jQuery( document.getElementById( 'frm_notification_settings' ) );\n\n\t\t\tlet formSettings, $loggedIn, $cookieExp, $editable;\n\n\t\t\t// BCC, CC, and Reply To button functionality\n\t\t\t$formActions.on( 'click', '.frm_email_buttons', showEmailRow );\n\t\t\t$formActions.on( 'click', '.frm_remove_field', hideEmailRow );\n\t\t\t$formActions.on( 'change', '.frm_to_row, .frm_from_row', showEmailWarning );\n\t\t\t$formActions.on( 'change', '.frm_tax_selector', changePosttaxRow );\n\t\t\t$formActions.on( 'change', 'select.frm_single_post_field', checkDupPost );\n\t\t\t$formActions.on( 'change', 'select.frm_toggle_post_content', togglePostContent );\n\t\t\t$formActions.on( 'change', 'select.frm_dyncontent_opt', fillDyncontent );\n\t\t\t$formActions.on( 'change', '.frm_post_type', switchPostType );\n\t\t\t$formActions.on( 'click', '.frm_add_postmeta_row', addPostmetaRow );\n\t\t\t$formActions.on( 'click', '.frm_add_posttax_row', addPosttaxRow );\n\t\t\t$formActions.on( 'click', '.frm_toggle_cf_opts', toggleCfOpts );\n\t\t\t$formActions.on( 'click', '.frm_duplicate_form_action', copyFormAction );\n\t\t\tjQuery( '.frm_actions_list' ).on( 'click', '.frm_active_action', addFormAction );\n\t\t\tjQuery( '#frm-show-groups, #frm-hide-groups' ).on( 'click', toggleActionGroups );\n\t\t\tinitiateMultiselect();\n\n\t\t\t//set actions icons to inactive\n\t\t\tjQuery( 'ul.frm_actions_list li' ).each( function() {\n\t\t\t\tcheckActiveAction( jQuery( this ).children( 'a' ).data( 'actiontype' ) );\n\n\t\t\t\t// If the icon is a background image, don't add BG color.\n\t\t\t\tconst icon = jQuery( this ).find( 'i' );\n\t\t\t\tif ( icon.css( 'background-image' ) !== 'none' ) {\n\t\t\t\t\ticon.addClass( 'frm-inverse' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tjQuery( '.frm_submit_settings_btn' ).on( 'click', submitSettings );\n\n\t\t\taddFormNameModalEvents();\n\n\t\t\tformSettings = jQuery( '.frm_form_settings' );\n\t\t\tformSettings.on( 'click', '.frm_add_form_logic', addFormLogicRow );\n\t\t\tformSettings.on( 'click', '.frm_already_used', actionLimitMessage );\n\n\t\t\tdocument.addEventListener(\n\t\t\t\t'click',\n\t\t\t\tfunction handleImageUploadClickEvents( event ) {\n\t\t\t\t\tconst { target } = event;\n\n\t\t\t\t\tif ( ! target.closest( '.frm_image_preview_wrapper' ) ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( target.closest( '.frm_choose_image_box' ) ) {\n\t\t\t\t\t\taddImageToOption.bind( target )( event );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( target.closest( '.frm_remove_image_option' ) ) {\n\t\t\t\t\t\tremoveImageFromOption.bind( target )( event );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t// Close shortcode modal on click.\n\t\t\tformSettings.on( 'mouseup', '*:not(.frm-show-box)', maybeHideShortcodes );\n\n\t\t\t//Warning when user selects \"Do not store entries ...\"\n\t\t\tjQuery( document.getElementById( 'no_save' ) ).on( 'change', function() {\n\t\t\t\tif ( this.checked ) {\n\t\t\t\t\tif ( confirm( frmAdminJs.no_save_warning ) !== true ) {\n\t\t\t\t\t\t// Uncheck box if user hits \"Cancel\"\n\t\t\t\t\t\tjQuery( this ).attr( 'checked', false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tjQuery( 'select[name=\"options[edit_action]\"]' ).on( 'change', showSuccessOpt );\n\n\t\t\t$loggedIn = document.getElementById( 'logged_in' );\n\t\t\tjQuery( $loggedIn ).on( 'change', function() {\n\t\t\t\tif ( this.checked ) {\n\t\t\t\t\tvisible( '.hide_logged_in' );\n\t\t\t\t} else {\n\t\t\t\t\tinvisible( '.hide_logged_in' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t$cookieExp = jQuery( document.getElementById( 'frm_cookie_expiration' ) );\n\t\t\tjQuery( document.getElementById( 'frm_single_entry_type' ) ).on( 'change', function() {\n\t\t\t\tif ( this.value === 'cookie' ) {\n\t\t\t\t\t$cookieExp.fadeIn( 'slow' );\n\t\t\t\t} else {\n\t\t\t\t\t$cookieExp.fadeOut( 'slow' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tconst $singleEntry = document.getElementById( 'single_entry' );\n\t\t\tjQuery( $singleEntry ).on( 'change', function() {\n\t\t\t\tif ( this.checked ) {\n\t\t\t\t\tvisible( '.hide_single_entry' );\n\t\t\t\t} else {\n\t\t\t\t\tinvisible( '.hide_single_entry' );\n\t\t\t\t}\n\n\t\t\t\tif ( this.checked && jQuery( document.getElementById( 'frm_single_entry_type' ) ).val() === 'cookie' ) {\n\t\t\t\t\t$cookieExp.fadeIn( 'slow' );\n\t\t\t\t} else {\n\t\t\t\t\t$cookieExp.fadeOut( 'slow' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tjQuery( '.hide_save_draft' ).hide();\n\n\t\t\tconst $saveDraft = jQuery( document.getElementById( 'save_draft' ) );\n\t\t\t$saveDraft.on( 'change', function() {\n\t\t\t\tif ( this.checked ) {\n\t\t\t\t\tjQuery( '.hide_save_draft' ).fadeIn( 'slow' );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery( '.hide_save_draft' ).fadeOut( 'slow' );\n\t\t\t\t}\n\t\t\t} );\n\t\t\ttriggerChange( $saveDraft );\n\n\t\t\t//If Allow editing is checked/unchecked\n\t\t\t$editable = document.getElementById( 'editable' );\n\t\t\tjQuery( $editable ).on( 'change', function() {\n\t\t\t\tif ( this.checked ) {\n\t\t\t\t\tjQuery( '.hide_editable' ).fadeIn( 'slow' );\n\t\t\t\t\ttriggerChange( document.getElementById( 'edit_action' ) );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery( '.hide_editable' ).fadeOut( 'slow' );\n\t\t\t\t\tjQuery( '.edit_action_message_box' ).fadeOut( 'slow' );//Hide On Update message box\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t//If File Protection is checked/unchecked\n\t\t\tjQuery( document ).on( 'change', '#protect_files', function() {\n\t\t\t\tif ( this.checked ) {\n\t\t\t\t\tjQuery( '.hide_protect_files' ).fadeIn( 'slow' );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery( '.hide_protect_files' ).fadeOut( 'slow' );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tjQuery( document ).on( 'frm-multiselect-changed', '#protect_files_role', adjustVisibilityValuesForEveryoneValues );\n\n\t\t\tjQuery( document ).on( 'submit', '.frm_form_settings', settingsSubmitted );\n\t\t\tjQuery( document ).on( 'change', '#form_settings_page input:not(.frm-search-input), #form_settings_page select, #form_settings_page textarea', fieldUpdated );\n\n\t\t\t// Page Selection Autocomplete\n\t\t\tinitAutocomplete();\n\n\t\t\tjQuery( document ).on( 'frm-action-loaded', onActionLoaded );\n\n\t\t\tinitOnSubmitAction();\n\n\t\t\twp.hooks.addAction( 'frm_reset_fields_updated', 'formidableAdmin', resetFieldsUpdated );\n\t\t},\n\n\t\tpanelInit: function() {\n\t\t\tlet customPanel, settingsPage, viewPage, insertFieldsTab;\n\n\t\t\tjQuery( '.frm_wrap, #postbox-container-1' ).on( 'click', '.frm_insert_code', insertCode );\n\t\t\tjQuery( document ).on( 'change', '.frm_insert_val', function() {\n\t\t\t\tinsertFieldCode( jQuery( this ).data( 'target' ), jQuery( this ).val() );\n\t\t\t\tjQuery( this ).val( '' );\n\t\t\t} );\n\n\t\t\tjQuery( document ).on( 'click change', '[name=\"frm-id-key-condition\"]', resetLogicBuilder );\n\t\t\tjQuery( document ).on( 'keyup change', '.frm-build-logic', setLogicExample );\n\n\t\t\tshowInputIcon();\n\t\t\tjQuery( document ).on( 'frmElementAdded', function( event, parentEle ) {\n\t\t\t\t/* This is here for add-ons to trigger */\n\t\t\t\tshowInputIcon( parentEle );\n\t\t\t} );\n\t\t\tjQuery( document ).on( 'mousedown', '.frm-show-box', showShortcodes );\n\n\t\t\tsettingsPage = document.getElementById( 'form_settings_page' );\n\t\t\tviewPage = document.body.classList.contains( 'post-type-frm_display' );\n\t\t\tinsertFieldsTab = document.getElementById( 'frm_insert_fields_tab' );\n\n\t\t\tif ( settingsPage !== null || viewPage || builderPage ) {\n\t\t\t\tjQuery( document ).on( 'focusin', 'form input, form textarea', function( e ) {\n\t\t\t\t\tlet htmlTab;\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\tmaybeShowModal( this );\n\n\t\t\t\t\tif ( jQuery( this ).is( ':not(:submit, input[type=button], .frm-search-input, input[type=checkbox])' ) ) {\n\t\t\t\t\t\tif ( jQuery( e.target ).closest( '#frm_adv_info' ).length ) {\n\t\t\t\t\t\t// Don't trigger for fields inside of the modal.\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( settingsPage !== null || builderPage ) {\n\t\t\t\t\t\t/* form settings page */\n\t\t\t\t\t\t\thtmlTab = jQuery( '#frm_html_tab' );\n\t\t\t\t\t\t\tif ( jQuery( this ).closest( '#html_settings' ).length > 0 ) {\n\t\t\t\t\t\t\t\thtmlTab.show();\n\t\t\t\t\t\t\t\thtmlTab.siblings().hide();\n\t\t\t\t\t\t\t\tjQuery( '#frm_html_tab a' ).trigger( 'click' );\n\t\t\t\t\t\t\t\ttoggleAllowedHTML( this );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tshowElement( jQuery( '.frm-category-tabs li' ) );\n\t\t\t\t\t\t\t\tinsertFieldsTab.click();\n\t\t\t\t\t\t\t\thtmlTab.hide();\n\t\t\t\t\t\t\t\thtmlTab.siblings().show();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if ( viewPage ) {\n\t\t\t\t\t\t\tconst event = new CustomEvent( 'frm_legacy_views_handle_field_focus' );\n\t\t\t\t\t\t\tevent.frmData = { idAttrValue: this.id };\n\t\t\t\t\t\t\tdocument.dispatchEvent( event );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tjQuery( '.frm_wrap, #postbox-container-1' ).on( 'mousedown', '#frm_adv_info a, .frm_field_list a', function( e ) {\n\t\t\t\te.preventDefault();\n\t\t\t} );\n\n\t\t\tcustomPanel = jQuery( '#frm_adv_info' );\n\t\t\tcustomPanel.on( 'click', '.subsubsub a.frmids', function( e ) {\n\t\t\t\ttoggleKeyID( 'frmids', e );\n\t\t\t} );\n\t\t\tcustomPanel.on( 'click', '.subsubsub a.frmkeys', function( e ) {\n\t\t\t\ttoggleKeyID( 'frmkeys', e );\n\t\t\t} );\n\t\t},\n\n\t\tinboxInit: function() {\n\t\t\tjQuery( '.frm_inbox_dismiss' ).on( 'click', function( e ) {\n\t\t\t\tconst message = this.parentNode.parentNode;\n\t\t\t\tconst key = message.getAttribute( 'data-message' );\n\t\t\t\tconst href = this.getAttribute( 'href' );\n\t\t\t\tconst dismissedMessage = message.cloneNode( true );\n\t\t\t\tconst dismissedMessagesWrapper = document.querySelector( '.frm-dismissed-inbox-messages' );\n\n\t\t\t\tif ( 'free_templates' === key && ! this.classList.contains( 'frm_inbox_dismiss' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\te.preventDefault();\n\n\t\t\t\tdata = {\n\t\t\t\t\taction: 'frm_inbox_dismiss',\n\t\t\t\t\tkey,\n\t\t\t\t\tnonce: frmGlobal.nonce\n\t\t\t\t};\n\n\t\t\t\tconst isInboxSlideIn = 'frm_inbox_slide_in' === message.id;\n\t\t\t\tif ( isInboxSlideIn ) {\n\t\t\t\t\tmessage.classList.remove( 's11-fadein' );\n\t\t\t\t\tmessage.classList.add( 's11-fadeout' );\n\t\t\t\t\tmessage.addEventListener( 'animationend', () => message.remove(), { once: true } );\n\t\t\t\t}\n\n\t\t\t\tpostAjax(\n\t\t\t\t\tdata,\n\t\t\t\t\t() => {\n\t\t\t\t\t\tif ( isInboxSlideIn ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( href !== '#' ) {\n\t\t\t\t\t\t\twindow.location = href;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfadeOut(\n\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\t\tif ( null !== dismissedMessagesWrapper ) {\n\t\t\t\t\t\t\t\t\tdismissedMessage.classList.remove( 'frm-fade' );\n\t\t\t\t\t\t\t\t\tdismissedMessage.querySelector( '.frm-inbox-message-heading' )?.removeChild( dismissedMessage.querySelector( '.frm-inbox-message-heading .frm_inbox_dismiss' ) );\n\t\t\t\t\t\t\t\t\tdismissedMessagesWrapper.append( dismissedMessage );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( 1 === message.parentNode.querySelectorAll( '.frm-inbox-message-container' ).length ) {\n\t\t\t\t\t\t\t\t\tdocument.getElementById( 'frm_empty_inbox' ).classList.remove( 'frm_hidden' );\n\t\t\t\t\t\t\t\t\tmessage.parentNode.closest( '.frm-active' ).classList.add( 'frm-empty-inbox' );\n\t\t\t\t\t\t\t\t\tshowActiveCampaignForm();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tmessage.parentNode.removeChild( message );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} );\n\n\t\t\tif ( false === document.getElementById( 'frm_empty_inbox' )?.classList.contains( 'frm_hidden' ) ) {\n\t\t\t\tshowActiveCampaignForm();\n\t\t\t}\n\t\t},\n\n\t\tsolutionInit: function() {\n\t\t\tjQuery( document ).on( 'submit', '#frm-new-template', installTemplate );\n\t\t},\n\n\t\tstyleInit: function() {\n\t\t\tconst $previewWrapper = jQuery( '.frm_image_preview_wrapper' );\n\t\t\t$previewWrapper.on( 'click', '.frm_choose_image_box', addImageToOption );\n\t\t\t$previewWrapper.on( 'click', '.frm_remove_image_option', removeImageFromOption );\n\n\t\t\twp.hooks.doAction( 'frm_style_editor_init' );\n\t\t},\n\n\t\tcustomCSSInit: function() {\n\t\t\tconsole.warn( 'Calling frmAdminBuild.customCSSInit is deprecated.' );\n\t\t},\n\n\t\tglobalSettingsInit: function() {\n\t\t\tlet licenseTab;\n\n\t\t\tjQuery( document ).on( 'click', '[data-frmuninstall]', uninstallNow );\n\n\t\t\tinitiateMultiselect();\n\n\t\t\t// activate addon licenses\n\t\t\tlicenseTab = document.getElementById( 'licenses_settings' );\n\t\t\tif ( licenseTab !== null ) {\n\t\t\t\tjQuery( licenseTab ).on( 'click', '.edd_frm_save_license', saveAddonLicense );\n\t\t\t}\n\n\t\t\t// Solution install page\n\t\t\tjQuery( document ).on( 'click', '#frm-new-template button', installTemplateFieldset );\n\n\t\t\tjQuery( '#frm-dismissable-cta .dismiss' ).on( 'click', function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tjQuery.post(\n\t\t\t\t\tajaxurl,\n\t\t\t\t\t{\n\t\t\t\t\t\taction: 'frm_lite_settings_upgrade',\n\t\t\t\t\t\tnonce: frmGlobal.nonce\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tjQuery( '.settings-lite-cta' ).remove();\n\t\t\t} );\n\n\t\t\tconst captchaType = document.getElementById( 'frm_re_type' );\n\t\t\tif ( captchaType ) {\n\t\t\t\tcaptchaType.addEventListener( 'change', handleCaptchaTypeChange );\n\t\t\t}\n\n\t\t\tdocument.querySelector( '.frm_captchas' ).addEventListener( 'change', function( event ) {\n\t\t\t\tconst captchaValueOnLoad = document.querySelector( '.frm_captchas input[checked=\"checked\"]' )?.value;\n\t\t\t\tconst showNote = event.target.value !== captchaValueOnLoad;\n\t\t\t\tdocument.querySelector( '.captcha_settings .frm_note_style' ).classList.toggle( 'frm_hidden', ! showNote );\n\t\t\t} );\n\n\t\t\t// Set fieldsUpdated to 0 to avoid the unsaved changes pop up.\n\t\t\tfrmDom.util.documentOn( 'submit', '.frm_settings_form', () => fieldsUpdated = 0 );\n\n\t\t\tconst manageStyleSettings = document.getElementById( 'manage_styles_settings' );\n\t\t\tif ( manageStyleSettings ) {\n\t\t\t\tmanageStyleSettings.addEventListener(\n\t\t\t\t\t'change',\n\t\t\t\t\tevent => {\n\t\t\t\t\t\tconst target = event.target;\n\t\t\t\t\t\tif ( 'SELECT' !== target.nodeName || ! target.dataset.name || target.getAttribute( 'name' ) ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttarget.setAttribute( 'name', target.dataset.name );\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst paymentsSettings = document.getElementById( 'payments_settings' );\n\t\t\tconst paymentSettingsTabs = paymentsSettings?.querySelectorAll( '[name=\"frm_payment_section\"]' );\n\t\t\tif ( paymentSettingsTabs ) {\n\t\t\t\tpaymentSettingsTabs.forEach(\n\t\t\t\t\telement => {\n\t\t\t\t\t\telement.addEventListener( 'change', () => {\n\t\t\t\t\t\t\tif ( ! element.checked ) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst label = paymentsSettings.querySelector( `label[for=\"${ element.id }\"]` );\n\t\t\t\t\t\t\tif ( label ) {\n\t\t\t\t\t\t\t\tlabel.setAttribute( 'aria-selected', 'true' );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tpaymentSettingsTabs.forEach(\n\t\t\t\t\t\t\t\ttab => {\n\t\t\t\t\t\t\t\t\tif ( tab === element ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tconst label = paymentsSettings.querySelector( `label[for=\"${ tab.id }\"]` );\n\t\t\t\t\t\t\t\t\tif ( label ) {\n\t\t\t\t\t\t\t\t\t\tlabel.setAttribute( 'aria-selected', 'false' );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\texportInit: function() {\n\t\t\tjQuery( '.frm_form_importer' ).on( 'submit', startFormMigration );\n\t\t\tjQuery( document.getElementById( 'frm_export_xml' ) ).on( 'submit', validateExport );\n\t\t\tjQuery( '#frm_export_xml input, #frm_export_xml select' ).on( 'change', removeExportError );\n\t\t\tjQuery( 'input[name=\"frm_import_file\"]' ).on( 'change', checkCSVExtension );\n\t\t\tdocument.querySelector( 'select[name=\"format\"]' ).addEventListener( 'change', exportTypeChanged );\n\n\t\t\tjQuery( 'input[name=\"frm_export_forms[]\"]' ).on( 'click', preventMultipleExport );\n\t\t\tinitiateMultiselect();\n\n\t\t\tjQuery( '.frm-feature-banner .dismiss' ).on( 'click', function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tjQuery.post( ajaxurl, {\n\t\t\t\t\taction: 'frm_dismiss_migrator',\n\t\t\t\t\tplugin: this.id,\n\t\t\t\t\tnonce: frmGlobal.nonce\n\t\t\t\t} );\n\t\t\t\tthis.parentElement.remove();\n\t\t\t} );\n\n\t\t\tshowOrHideRepeaters( getExportOption() );\n\n\t\t\tdocument.querySelector( '#frm-export-select-all' ).addEventListener( 'change', event => {\n\t\t\t\tdocument.querySelectorAll( '[name=\"frm_export_forms[]\"]' ).forEach( cb => cb.checked = event.target.checked );\n\t\t\t} );\n\t\t},\n\n\t\tinboxBannerInit: function() {\n\t\t\tconst banner = document.getElementById( 'frm_banner' );\n\t\t\tif ( ! banner ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst dismissButton = banner.querySelector( '.frm-banner-dismiss' );\n\t\t\tdocument.addEventListener(\n\t\t\t\t'click',\n\t\t\t\tfunction( event ) {\n\t\t\t\t\tif ( event.target !== dismissButton ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = {\n\t\t\t\t\t\taction: 'frm_inbox_dismiss',\n\t\t\t\t\t\tkey: banner.dataset.key,\n\t\t\t\t\t\tnonce: frmGlobal.nonce\n\t\t\t\t\t};\n\t\t\t\t\tpostAjax(\n\t\t\t\t\t\tdata,\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\tjQuery( banner ).fadeOut(\n\t\t\t\t\t\t\t\t400,\n\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\tbanner.remove();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\t},\n\n\t\tupdateOpts: function( fieldId, opts, modal ) {\n\t\t\tconst separate = usingSeparateValues( fieldId ),\n\t\t\t\taction = isProductField( fieldId ) ? 'frm_bulk_products' : 'frm_import_options';\n\t\t\tjQuery.ajax( {\n\t\t\t\ttype: 'POST',\n\t\t\t\turl: ajaxurl,\n\t\t\t\tdata: {\n\t\t\t\t\taction: action,\n\t\t\t\t\tfield_id: fieldId,\n\t\t\t\t\topts: opts,\n\t\t\t\t\tseparate: separate,\n\t\t\t\t\tnonce: frmGlobal.nonce\n\t\t\t\t},\n\t\t\t\tsuccess: function( html ) {\n\t\t\t\t\tdocument.getElementById( 'frm_field_' + fieldId + '_opts' ).innerHTML = html;\n\t\t\t\t\twp.hooks.doAction( 'frm_after_bulk_edit_opts', fieldId );\n\t\t\t\t\tresetDisplayedOpts( fieldId );\n\n\t\t\t\t\tif ( typeof modal !== 'undefined' ) {\n\t\t\t\t\t\tmodal.dialog( 'close' );\n\t\t\t\t\t\tdocument.getElementById( 'frm-update-bulk-opts' ).classList.remove( 'frm_loading_button' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\t/* remove conditional logic if the field doesn't exist */\n\t\ttriggerRemoveLogic: function( fieldID, metaName ) {\n\t\t\tjQuery( '#frm_logic_' + fieldID + '_' + metaName + ' .frm_remove_tag' ).trigger( 'click' );\n\t\t},\n\n\t\tdownloadXML: function( controller, ids, isTemplate ) {\n\t\t\tlet url = ajaxurl + '?action=frm_' + controller + '_xml&ids=' + ids;\n\t\t\tif ( isTemplate !== null ) {\n\t\t\t\turl = url + '&is_template=' + isTemplate;\n\t\t\t}\n\t\t\tlocation.href = url;\n\t\t},\n\n\t\t/**\n\t\t * @since 5.0.04\n\t\t */\n\t\thooks: {\n\t\t\tapplyFilters: function( hookName, ...args ) {\n\t\t\t\treturn wp.hooks.applyFilters( hookName, ...args );\n\t\t\t},\n\t\t\taddFilter: function( hookName, callback, priority ) {\n\t\t\t\treturn wp.hooks.addFilter( hookName, 'formidable', callback, priority );\n\t\t\t},\n\t\t\tdoAction: function( hookName, ...args ) {\n\t\t\t\treturn wp.hooks.doAction( hookName, ...args );\n\t\t\t},\n\t\t\taddAction: function( hookName, callback, priority ) {\n\t\t\t\treturn wp.hooks.addAction( hookName, 'formidable', callback, priority );\n\t\t\t}\n\t\t},\n\n\t\tapplyZebraStriping,\n\t\tinitModal,\n\t\tinfoModal,\n\t\toffsetModalY,\n\t\tadjustConditionalLogicOptionOrders,\n\t\taddRadioCheckboxOpt,\n\t\tinstallNewForm,\n\t\ttoggleAddonState,\n\t\tpurifyHtml,\n\t\tloadApiEmailForm,\n\t\taddMyEmailAddress,\n\t\tfillDropdownOpts,\n\t\tshowSaveAndReloadModal,\n\t\tclearSettingsBox,\n\t\tdeleteField,\n\t\tinsertFormField,\n\t\tconfirmLinkClick,\n\t\thandleInsertFieldByDraggingResponse,\n\t\thandleAddFieldClickResponse,\n\t\tsyncLayoutClasses,\n\t\tmoveFieldSettings,\n\t};\n};\n\nwindow.frmAdminBuild = frmAdminBuildJS();\n\njQuery( document ).ready(\n\t() => {\n\t\tfrmAdminBuild.init();\n\n\t\tfrmDom.bootstrap.setupBootstrapDropdowns( convertOldBootstrapDropdownsToBootstrap4 );\n\t\tdocument.querySelector( '.preview.dropdown .frm-dropdown-toggle' )?.setAttribute( 'data-toggle', 'dropdown' );\n\n\t\tfunction convertOldBootstrapDropdownsToBootstrap4( frmDropdownMenu ) {\n\t\t\tconst toggle = frmDropdownMenu.querySelector( '.frm-dropdown-toggle' );\n\t\t\tif ( toggle ) {\n\t\t\t\tif ( ! toggle.hasAttribute( 'role' ) ) {\n\t\t\t\t\ttoggle.setAttribute( 'role', 'button' );\n\t\t\t\t}\n\t\t\t\tif ( ! toggle.hasAttribute( 'tabindex' ) ) {\n\t\t\t\t\ttoggle.setAttribute( 'tabindex', 0 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Convert