/* exported frm_add_logic_row, frm_remove_tag, frm_show_div, frmCheckAll, frmCheckAllLevel */ var frmAdminBuild; var FrmFormsConnect = window.FrmFormsConnect || ( function( document, window, $ ) { /*global jQuery:false, frm_admin_js, frmGlobal, ajaxurl */ var el = { licenseBox: document.getElementById( 'frm_license_top' ), messageBox: document.getElementsByClassName( 'frm_pro_license_msg' )[0], btn: document.getElementById( 'frm-settings-connect-btn' ), reset: document.getElementById( 'frm_reconnect_link' ) }; /** * Public functions and properties. * * @since 4.03 * * @type {Object} */ var app = { /** * Register connect button event. * * @since 4.03 */ init: function() { $( document.getElementById( 'frm_deauthorize_link' ) ).on( 'click', app.deauthorize ); $( '.frm_authorize_link' ).on( 'click', app.authorize ); if ( el.reset !== null ) { $( el.reset ).on( 'click', app.reauthorize ); } $( el.btn ).on( 'click', function( e ) { e.preventDefault(); app.gotoUpgradeUrl(); }); window.addEventListener( 'message', function( msg ) { if ( msg.origin.replace( /\/$/, '' ) !== frmGlobal.app_url.replace( /\/$/, '' ) ) { return; } if ( ! msg.data || 'object' !== typeof msg.data ) { console.error( 'Messages from "' + frmGlobal.app_url + '" must contain an api key string.' ); return; } app.updateForm( msg.data ); }); jQuery( document ).on( 'mouseover', '#frm_new_form_modal .frm-selectable', function() { var $item = jQuery( this ), $icons = $item.find( '.frm-hover-icons' ), $clone; if ( ! $icons.length ) { $clone = jQuery( '#frm-hover-icons-template' ).clone(); $clone.removeAttr( 'id' ); $item.append( $clone ); } $icons.show(); }); jQuery( document ).on( 'mouseout', '#frm_new_form_modal .frm-selectable', function() { var $item = jQuery( this ), $icons = $item.find( '.frm-hover-icons' ); if ( $icons.length ) { $icons.hide(); } }); }, /** * Go to upgrade url. * * @since 4.03 */ gotoUpgradeUrl: function() { var w = window.open( frmGlobal.app_url + '/api-connect/', '_blank', 'location=no,width=500,height=730,scrollbars=0' ); w.focus(); }, updateForm: function( response ) { // Start spinner. var btn = el.btn; btn.classList.add( 'frm_loading_button' ); if ( response.url !== '' ) { app.showProgress({ success: true, message: 'Installing...' }); var fallback = setTimeout( function() { app.showProgress({ success: true, message: 'Installing is taking longer than expected. Install Now' }); }, 10000 ); $.ajax({ type: 'POST', url: ajaxurl, dataType: 'json', data: { action: 'frm_connect', plugin: response.url, nonce: frmGlobal.nonce }, success: function() { clearTimeout( fallback ); app.activateKey( response ); }, error: function( xhr, textStatus, e ) { clearTimeout( fallback ); btn.classList.remove( 'frm_loading_button' ); app.showMessage({ success: false, message: e }); } }); } else if ( response.key !== '' ) { app.activateKey( response ); } }, activateKey: function( response ) { var btn = el.btn; if ( response.key === '' ) { btn.classList.remove( 'frm_loading_button' ); } else { app.showProgress({ success: true, message: 'Activating...' }); $.ajax({ type: 'POST', url: ajaxurl, dataType: 'json', data: { action: 'frm_addon_activate', license: response.key, plugin: 'formidable_pro', wpmu: 0, nonce: frmGlobal.nonce }, success: function( msg ) { btn.classList.remove( 'frm_loading_button' ); if ( msg.success === true ) { el.licenseBox.classList.replace( 'frm_unauthorized_box', 'frm_authorized_box' ); } app.showMessage( msg ); }, error: function( xhr, textStatus, e ) { btn.classList.remove( 'frm_loading_button' ); app.showMessage({ success: false, message: e }); } }); } }, /* Manual license authorization */ authorize: function() { /*jshint validthis:true */ var button = this; var pluginSlug = this.getAttribute( 'data-plugin' ); var input = document.getElementById( 'edd_' + pluginSlug + '_license_key' ); var license = input.value; var wpmu = document.getElementById( 'proplug-wpmu' ); this.classList.add( 'frm_loading_button' ); if ( wpmu === null ) { wpmu = 0; } else if ( wpmu.checked ) { wpmu = 1; } else { wpmu = 0; } $.ajax({ type: 'POST', url: ajaxurl, dataType: 'json', data: { action: 'frm_addon_activate', license: license, plugin: pluginSlug, wpmu: wpmu, nonce: frmGlobal.nonce }, success: function( msg ) { app.afterAuthorize( msg, input ); button.classList.remove( 'frm_loading_button' ); } }); }, afterAuthorize: function( msg, input ) { if ( msg.success === true ) { input.value = '•••••••••••••••••••'; } app.showMessage( msg ); }, showProgress: function( msg ) { var messageBox = el.messageBox; if ( msg.success === true ) { messageBox.classList.remove( 'frm_error_style' ); messageBox.classList.add( 'frm_message', 'frm_updated_message' ); } else { messageBox.classList.add( 'frm_error_style' ); messageBox.classList.remove( 'frm_message', 'frm_updated_message' ); } messageBox.classList.remove( 'frm_hidden' ); messageBox.innerHTML = msg.message; }, showMessage: function( msg ) { var messageBox = el.messageBox; if ( msg.success === true ) { var d = el.licenseBox; d.className = d.className.replace( 'frm_unauthorized_box', 'frm_authorized_box' ); messageBox.classList.remove( 'frm_error_style' ); messageBox.classList.add( 'frm_message', 'frm_updated_message' ); } else { messageBox.classList.add( 'frm_error_style' ); messageBox.classList.remove( 'frm_message', 'frm_updated_message' ); } messageBox.classList.remove( 'frm_hidden' ); messageBox.innerHTML = msg.message; if ( msg.message !== '' ) { setTimeout( function() { messageBox.innerHTML = ''; messageBox.classList.add( 'frm_hidden' ); messageBox.classList.remove( 'frm_error_style', 'frm_message', 'frm_updated_message' ); }, 10000 ); var refreshPage = document.querySelectorAll( '#frm-welcome' ); if ( refreshPage.length > 0 ) { window.location.reload(); } } }, /* Clear the site license cache */ reauthorize: function() { /*jshint validthis:true */ this.innerHTML = ''; $.ajax({ type: 'POST', url: ajaxurl, dataType: 'json', data: { action: 'frm_reset_cache', plugin: 'formidable_pro', nonce: frmGlobal.nonce }, success: function( msg ) { el.reset.innerHTML = msg.message; if ( el.reset.getAttribute( 'data-refresh' ) === '1' ) { window.location.reload(); } } }); return false; }, deauthorize: function() { /*jshint validthis:true */ if ( ! confirm( frmGlobal.deauthorize ) ) { return false; } var pluginSlug = this.getAttribute( 'data-plugin' ), input = document.getElementById( 'edd_' + pluginSlug + '_license_key' ), license = input.value, link = this; this.innerHTML = ''; $.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_addon_deactivate', license: license, plugin: pluginSlug, nonce: frmGlobal.nonce }, success: function() { el.licenseBox.className = el.licenseBox.className.replace( 'frm_authorized_box', 'frm_unauthorized_box' ); input.value = ''; link.innerHTML = ''; } }); return false; } }; // Provide access to public functions/properties. return app; }( document, window, jQuery ) ); function frmAdminBuildJS() { //'use strict'; /*global jQuery:false, frm_admin_js, frmGlobal, ajaxurl */ var $newFields = jQuery( document.getElementById( 'frm-show-fields' ) ), builderForm = document.getElementById( 'new_fields' ), thisForm = document.getElementById( 'form_id' ), cancelSort = false, copyHelper = false, fieldsUpdated = 0, thisFormId = 0, autoId = 0, optionMap = {}, lastNewActionIdReturned = 0, __ = wp.i18n.__; if ( thisForm !== null ) { thisFormId = thisForm.value; } // Global settings var s; function showElement( element ) { element[0].style.display = ''; } function hideElement( element ) { element[0].style.display = 'none'; } function empty( $obj ) { if ( $obj !== null ) { while ( $obj.firstChild ) { $obj.removeChild( $obj.firstChild ); } } } function addClass( $obj, className ) { if ( $obj.classList ) { $obj.classList.add( className ); } else { $obj.className += ' ' + className; } } function confirmClick( e ) { /*jshint validthis:true */ e.stopPropagation(); e.preventDefault(); confirmLinkClick( this ); } function confirmLinkClick( link ) { var message = link.getAttribute( 'data-frmverify' ); if ( message === null || link.id === 'frm-confirmed-click' ) { return true; } else { return confirmModal( link ); } } function confirmModal( link ) { var caution, verify, $confirmMessage, frmCaution, i, dataAtts, $info = initModal( '#frm_confirm_modal', '400px' ), continueButton = document.getElementById( 'frm-confirmed-click' ); if ( $info === false ) { return false; } caution = link.getAttribute( 'data-frmcaution' ); verify = link.getAttribute( 'data-frmverify' ); $confirmMessage = jQuery( '.frm-confirm-msg' ); $confirmMessage.empty(); if ( caution ) { frmCaution = document.createElement( 'div' ); frmCaution.classList.add( 'frm-caution' ); frmCaution.appendChild( document.createTextNode( caution ) ); $confirmMessage.append( frmCaution ); } if ( verify ) { $confirmMessage.append( document.createTextNode( verify ) ); } removeAtts = continueButton.dataset; for ( i in dataAtts ) { continueButton.removeAttribute( 'data-' + i ); } dataAtts = link.dataset; for ( i in dataAtts ) { if ( i !== 'frmverify' ) { continueButton.setAttribute( 'data-' + i, dataAtts[i]); } } $info.dialog( 'open' ); continueButton.setAttribute( 'href', link.getAttribute( 'href' ) ); return false; } function infoModal( msg ) { var $info = initModal( '#frm_info_modal', '400px' ); if ( $info === false ) { return false; } jQuery( '.frm-info-msg' ).html( msg ); $info.dialog( 'open' ); return false; } function toggleItem( e ) { /*jshint validthis:true */ var toggle = this.getAttribute( 'data-frmtoggle' ), text = this.getAttribute( 'data-toggletext' ), items = jQuery( toggle ); e.preventDefault(); if ( items.is( ':visible' ) ) { items.show(); } else { items.hide(); } if ( text !== null && text !== '' ) { this.setAttribute( 'data-toggletext', this.innerHTML ); this.innerHTML = text; } return false; } function hideShowItem( e ) { /*jshint validthis:true */ var hide = this.getAttribute( 'data-frmhide' ), show = this.getAttribute( 'data-frmshow' ), toggleClass = this.getAttribute( 'data-toggleclass' ); e.preventDefault(); if ( toggleClass === null ) { toggleClass = 'frm_hidden'; } if ( hide !== null ) { jQuery( hide ).addClass( toggleClass ); } if ( show !== null ) { jQuery( show ).removeClass( toggleClass ); } var current = this.parentNode.querySelectorAll( 'a.current' ); if ( current !== null ) { for ( var i = 0; i < current.length; i++ ) { current[ i ].classList.remove( 'current' ); } this.classList.add( 'current' ); } return false; } function setupMenuOffset() { window.onscroll = document.documentElement.onscroll = setMenuOffset; setMenuOffset(); } function setMenuOffset() { var fields = document.getElementById( 'frm_adv_info' ); if ( fields === null ) { return; } var currentOffset = document.documentElement.scrollTop || document.body.scrollTop; // body for Safari if ( currentOffset === 0 ) { fields.classList.remove( 'frm_fixed' ); return; } var posEle = document.getElementById( 'frm_position_ele' ); if ( posEle === null ) { return; } var eleOffset = jQuery( posEle ).offset(); var offset = eleOffset.top; var desiredOffset = offset - currentOffset; var menuHeight = 0; var menu = document.getElementById( 'wpadminbar' ); if ( menu !== null ) { menuHeight = menu.offsetHeight; } if ( desiredOffset < menuHeight ) { desiredOffset = menuHeight; } if ( desiredOffset > menuHeight ) { fields.classList.remove( 'frm_fixed' ); } else { fields.classList.add( 'frm_fixed' ); if ( desiredOffset !== 32 ) { fields.style.top = desiredOffset + 'px'; } } } function loadTooltips() { var wrapClass = jQuery( '.wrap, .frm_wrap' ), confirmModal = document.getElementById( 'frm_confirm_modal' ), doAction = false, confirmedBulkDelete = false; jQuery( confirmModal ).on( 'click', '[data-deletefield]', deleteFieldConfirmed ); jQuery( confirmModal ).on( 'click', '[data-removeid]', removeThisTag ); jQuery( confirmModal ).on( 'click', '[data-trashtemplate]', trashTemplate ); wrapClass.on( 'click', '.frm_remove_tag, .frm_remove_form_action', removeThisTag ); wrapClass.on( 'click', 'a[data-frmverify]', confirmClick ); wrapClass.on( 'click', 'a[data-frmtoggle]', toggleItem ); wrapClass.on( 'click', 'a[data-frmhide], a[data-frmshow]', hideShowItem ); wrapClass.on( 'click', '.widget-top,a.widget-action', clickWidget ); wrapClass.on( 'mouseenter.frm', '.frm_bstooltip, .frm_help', function() { jQuery( this ).off( 'mouseenter.frm' ); jQuery( '.frm_bstooltip, .frm_help' ).tooltip( ); jQuery( this ).tooltip( 'show' ); }); jQuery( '.frm_bstooltip, .frm_help' ).tooltip( ); jQuery( document ).on( 'click', '#doaction, #doaction2', function( event ) { var isTop = this.id === 'doaction', suffix = isTop ? 'top' : 'bottom', bulkActionSelector = document.getElementById( 'bulk-action-selector-' + suffix ), confirmBulkDelete = document.getElementById( 'confirm-bulk-delete-' + suffix ); if ( bulkActionSelector !== null && confirmBulkDelete !== null ) { doAction = this; if ( ! confirmedBulkDelete && bulkActionSelector.value === 'bulk_delete' ) { event.preventDefault(); confirmLinkClick( confirmBulkDelete ); return false; } } else { doAction = false; } }); jQuery( document ).on( 'click', '#frm-confirmed-click', function( event ) { if ( doAction === false ) { return; } if ( this.getAttribute( 'href' ) === 'confirm-bulk-delete' ) { event.preventDefault(); confirmedBulkDelete = true; doAction.click(); return false; } }); } function deleteTooltips() { document.querySelectorAll( '.tooltip' ).forEach( function( tooltip ) { tooltip.remove(); } ); } function removeThisTag() { /*jshint validthis:true */ var show, hide, removeMore, id = '', deleteButton = jQuery( this ), continueRemove = confirmLinkClick( this ); if ( parseInt( this.getAttribute( 'data-skip-frm-js' ) ) ) { return; } if ( continueRemove === false ) { return; } else { id = deleteButton.attr( 'data-removeid' ); show = deleteButton.attr( 'data-showlast' ); removeMore = deleteButton.attr( 'data-removemore' ); if ( typeof show === 'undefined' ) { show = ''; } hide = deleteButton.attr( 'data-hidelast' ); if ( typeof hide === 'undefined' ) { hide = ''; } } if ( show !== '' ) { if ( deleteButton.closest( '.frm_add_remove' ).find( '.frm_remove_tag:visible' ).length > 1 ) { show = ''; hide = ''; } } else if ( id.indexOf( 'frm_postmeta_' ) === 0 ) { if ( jQuery( '#frm_postmeta_rows .frm_postmeta_row' ).length < 2 ) { show = '.frm_add_postmeta_row.button'; } if ( jQuery( '.frm_toggle_cf_opts' ).length && jQuery( '#frm_postmeta_rows .frm_postmeta_row:not(#' + id + ')' ).last().length ) { if ( show !== '' ) { show += ','; } show += '#' + jQuery( '#frm_postmeta_rows .frm_postmeta_row:not(#' + id + ')' ).last().attr( 'id' ) + ' .frm_toggle_cf_opts'; } } var $fadeEle = jQuery( document.getElementById( id ) ); $fadeEle.fadeOut( 400, function() { $fadeEle.remove(); fieldUpdated(); if ( hide !== '' ) { jQuery( hide ).hide(); } if ( show !== '' ) { jQuery( show + ' a,' + show ).removeClass( 'frm_hidden' ).fadeIn( 'slow' ); } var action = jQuery( this ).closest( '.frm_form_action_settings' ); if ( typeof action !== 'undefined' ) { var type = jQuery( this ).closest( '.frm_form_action_settings' ).find( '.frm_action_name' ).val(); checkActiveAction( type ); } }); if ( typeof removeMore !== 'undefined' ) { removeMore = jQuery( removeMore ); removeMore.fadeOut( 400, function() { removeMore.remove(); }); } if ( show !== '' ) { jQuery( this ).closest( '.frm_logic_rows' ).fadeOut( 'slow' ); } return false; } function clickWidget( event, b ) { /*jshint validthis:true */ var target = event.target; if ( typeof b === 'undefined' ) { b = this; } popCalcFields( b, false ); var cont = jQuery( b ).closest( '.frm_form_action_settings' ); if ( cont.length && typeof target !== 'undefined' ) { var className = target.parentElement.className; if ( 'string' === typeof className ) { if ( className.indexOf( 'frm_email_icons' ) > -1 || className.indexOf( 'frm_toggle' ) > -1 ) { // clicking on delete icon shouldn't open it event.stopPropagation(); return; } } } var inside = cont.children( '.widget-inside' ); if ( cont.length && inside.find( 'p, div, table' ).length < 1 ) { var actionId = cont.find( 'input[name$="[ID]"]' ).val(); var actionType = cont.find( 'input[name$="[post_excerpt]"]' ).val(); if ( actionType ) { inside.html( '' ); cont.find( '.spinner' ).fadeIn( 'slow' ); jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_form_action_fill', action_id: actionId, action_type: actionType, nonce: frmGlobal.nonce }, success: function( html ) { inside.html( html ); initiateMultiselect(); showInputIcon( '#' + cont.attr( 'id' ) ); initAutocomplete( 'page', inside ); jQuery( b ).trigger( 'frm-action-loaded' ); } }); } } jQuery( b ).closest( '.frm_field_box' ).siblings().find( '.widget-inside' ).slideUp( 'fast' ); if ( ( typeof b.className !== 'undefined' && b.className.indexOf( 'widget-action' ) !== -1 ) || jQuery( b ).closest( '.start_divider' ).length < 1 ) { return; } inside = jQuery( b ).closest( 'div.widget' ).children( '.widget-inside' ); if ( inside.is( ':hidden' ) ) { inside.slideDown( 'fast' ); } else { inside.slideUp( 'fast' ); } } function clickNewTab() { /*jshint validthis:true */ var t = this.getAttribute( 'href' ), c = t.replace( '#', '.' ), $link = jQuery( this ); if ( typeof t === 'undefined' ) { return false; } $link.closest( 'li' ).addClass( 'frm-tabs active' ).siblings( 'li' ).removeClass( 'frm-tabs active starttab' ); $link.closest( 'div' ).children( '.tabs-panel' ).not( t ).not( c ).hide(); document.getElementById( t.replace( '#', '' ) ).style.display = 'block'; if ( this.id === 'frm_insert_fields_tab' ) { clearSettingsBox(); } return false; } function clickTab( link, auto ) { link = jQuery( link ); var t = link.attr( 'href' ); if ( typeof t === 'undefined' ) { return; } var c = t.replace( '#', '.' ); link.closest( 'li' ).addClass( 'frm-tabs active' ).siblings( 'li' ).removeClass( 'frm-tabs active starttab' ); if ( link.closest( 'div' ).find( '.tabs-panel' ).length ) { link.closest( 'div' ).children( '.tabs-panel' ).not( t ).not( c ).hide(); } else { if ( document.getElementById( 'form_global_settings' ) !== null ) { /* global settings */ var ajax = link.data( 'frmajax' ); link.closest( '.frm_wrap' ).find( '.tabs-panel, .hide_with_tabs' ).hide(); if ( typeof ajax !== 'undefined' && ajax == '1' ) { loadSettingsTab( t ); } } else { /* form settings page */ jQuery( '#frm-categorydiv .tabs-panel, .hide_with_tabs' ).hide(); } } jQuery( t ).show(); jQuery( c ).show(); hideShortcodes(); if ( auto !== 'auto' ) { // Hide success message on tab change. jQuery( '.frm_updated_message' ).hide(); jQuery( '.frm_warning_style' ).hide(); } if ( jQuery( link ).closest( '#frm_adv_info' ).length ) { return; } if ( jQuery( '.frm_form_settings' ).length ) { jQuery( '.frm_form_settings' ).attr( 'action', '?page=formidable&frm_action=settings&id=' + jQuery( '.frm_form_settings input[name="id"]' ).val() + '&t=' + t.replace( '#', '' ) ); } else { jQuery( '.frm_settings_form' ).attr( 'action', '?page=formidable-settings&t=' + t.replace( '#', '' ) ); } } /* Form Builder */ function setupSortable( sort ) { var startSort, container, $previousFieldContainer, opts; startSort = false; container = jQuery( '#post-body-content' ); opts = { connectWith: 'ul.frm_sorting', items: 'li.frm_field_box', placeholder: 'sortable-placeholder', axis: 'y', cancel: '.widget,.frm_field_opts_list,input,textarea,select,.edit_field_type_end_divider,.frm_sortable_field_opts,.frm_noallow', accepts: 'field_type_list', forcePlaceholderSize: false, tolerance: 'pointer', handle: '.frm-move', over: function() { this.classList.add( 'drop-me' ); }, out: function() { this.classList.remove( 'drop-me' ); }, receive: function( event, ui ) { // Receive event occurs when an item in one sortable list is dragged into another sortable list if ( cancelSort ) { ui.item.addClass( 'frm_cancel_sort' ); return; } if ( typeof ui.item.attr( 'id' ) !== 'undefined' ) { if ( ui.item.attr( 'id' ).indexOf( 'frm_field_id' ) > -1 ) { // An existing field was dragged and dropped into, out of, or between sections updateFieldAfterMovingBetweenSections( ui.item ); } else { // A new field was dragged into the form insertNewFieldByDragging( this, ui.item, opts ); } } else if ( ui.item.hasClass( 'frm_field_box' ) ) { // dragging a group. getFieldsInRow( ui.item.children( 'ul' ) ).each( function() { updateFieldAfterMovingBetweenSections( jQuery( this ) ); } ); } }, change: function( event, ui ) { // don't allow some field types inside section if ( allowDrop( ui ) ) { ui.placeholder.addClass( 'sortable-placeholder' ).removeClass( 'no-drop-placeholder' ); cancelSort = false; } else { ui.placeholder.addClass( 'no-drop-placeholder' ).removeClass( 'sortable-placeholder' ); cancelSort = true; } }, start: function( event, ui ) { unselectFieldGroups(); deleteEmptyDividerWrappers(); maybeRemoveGroupHoverTarget(); closeOpenFieldDropdowns(); container.get( 0 ).classList.add( 'frm-dragging-field' ); if ( ui.item[0].offsetHeight > 120 ) { jQuery( sort ).sortable( 'refreshPositions' ); } if ( ui.item[0].classList.contains( 'frm-page-collapsed' ) ) { // If a page if collapsed, expand it before dragging since only the page break will move. toggleCollapsePage( jQuery( ui.item[0]) ); } $previousFieldContainer = ui.item.closest( 'ul.frm_sorting' ); }, helper: function( e, li ) { copyHelper = li.clone().insertAfter( li ); return li.clone().addClass( 'frm-sortable-helper' ); }, beforeStop: function( event, ui ) { // If this was dropped at the beginning of a collpased page, open it. var previous = ui.item[0].previousElementSibling; if ( previous !== null && previous.classList.contains( 'frm-page-collapsed' ) ) { toggleCollapsePage( jQuery( previous ) ); } }, stop: function( event, ui ) { var moving, $previousContainerFields, $closestFieldBox; container.get( 0 ).classList.remove( 'frm-dragging-field' ); moving = jQuery( this ); copyHelper && copyHelper.remove(); if ( cancelSort ) { moving.sortable( 'cancel' ); syncAfterDragAndDrop(); return; } $previousContainerFields = $previousFieldContainer.length ? getFieldsInRow( $previousFieldContainer ) : []; if ( $previousFieldContainer.length ) { if ( ! $previousContainerFields.length ) { $closestFieldBox = $previousFieldContainer.closest( 'li.frm_field_box' ); if ( ! $closestFieldBox.hasClass( 'edit_field_type_divider' ) ) { // remove an empty field group, but don't remove an empty section. $closestFieldBox.remove(); } } else { syncLayoutClasses( $previousContainerFields.first() ); } } if ( ( 'frm-show-fields' === ui.item.parent().attr( 'id' ) || ui.item.parent().hasClass( 'start_divider' ) ) && ui.item.hasClass( 'form-field' ) ) { // dragging an item into a new row. wrapFieldLiInPlace( ui.item ); if ( $previousContainerFields.length ) { // only if the previous container had other sibling fields, remove the previous layout class. syncLayoutClasses( ui.item ); } } else { syncLayoutClasses( ui.item ); } syncAfterDragAndDrop(); }, sort: function( event, ui ) { var $row, $children, $lastChild, currentIndex, left; container.scrollTop( function( i, v ) { var moved, h, relativePos, y; if ( startSort === false ) { startSort = event.clientY; return v; } moved = event.clientY - startSort; h = this.offsetHeight; relativePos = event.clientY - this.offsetTop; y = relativePos - h / 2; if ( relativePos > ( h - 50 ) && moved > 5 ) { // scrolling down return v + y * 0.1; } else if ( relativePos < 50 && moved < -5 ) { //scrolling up return v - Math.abs( y * 0.1 ); } }); maybeFixPlaceholderParent( ui, event ); $row = ui.placeholder.parent(); $children = getFieldsInRow( $row ); currentIndex = determineIndexBasedOffOfMousePositionInRow( $row, event.clientX ); if ( ! $children.length ) { return; } if ( currentIndex === $children.length ) { $lastChild = jQuery( $children.get( currentIndex - 1 ) ); left = $lastChild.offset().left - ui.placeholder.parent().offset().left + $lastChild.outerWidth(); $row.append( ui.placeholder ); } else { left = jQuery( $children.get( currentIndex ) ).offset().left - $row.offset().left; jQuery( $children.get( currentIndex ) ).before( ui.placeholder ); } ui.placeholder.get( 0 ).style.left = left + 'px'; } }; jQuery( sort ).sortable( opts ); setupFieldOptionSorting( jQuery( '#frm_builder_page' ) ); } function syncAfterDragAndDrop() { maybeRemoveNewCancelledFields(); maybeUncancelFields(); maybeFixEndDividers(); fixUnwrappedListItems(); toggleSectionHolder(); updateFieldOrder(); const event = new Event( 'frm_sync_after_drag_and_drop', { bubbles: false }); document.dispatchEvent( event ); } function maybeRemoveNewCancelledFields() { Array.from( document.getElementById( 'frm-show-fields' ).children ).forEach( function( fieldBox ) { if ( fieldBox.classList.contains( 'frmbutton' ) && fieldBox.classList.contains( 'ui-draggable' ) ) { fieldBox.remove(); } } ); } function maybeUncancelFields() { document.querySelectorAll( '.frm_cancel_sort' ).forEach( function( field ) { field.classList.remove( 'frm_cancel_sort' ); } ); } /** * Make sure the end dividers are always a child of a start divider, at the bottom at the list. */ function maybeFixEndDividers() { var endDividers = document.querySelectorAll( '.edit_field_type_end_divider' ); if ( ! endDividers.length ) { return; } endDividers.forEach( function( endDivider ) { if ( endDivider.parentNode.classList.contains( 'start_divider' ) ) { // avoid having to call closest, but still append it as it might not be the last child. endDivider.parentNode.appendChild( endDivider ); return; } endDivider.closest( '.start_divider' ).appendChild( endDivider ); } ); } /** * Sortable struggles to put the field into the proper section if there are multiple in a field group. This helps fix some of those issues. */ function maybeFixPlaceholderParent( ui, event ) { var elementFromPoint, wrapper, shouldAppend; elementFromPoint = document.elementFromPoint( event.clientX, event.clientY ); if ( null === elementFromPoint ) { return; } wrapper = elementFromPoint.closest( '.frm_sorting' ); if ( null === wrapper ) { return; } if ( ui.placeholder.closest( '.start_divider' ).parent().parent().find( '.start_divider' ).length < 2 ) { // placeholder is not in a problematic position that needs to be fixed so leave it. return; } shouldAppend = false; if ( wrapper.classList.contains( 'start_divider' ) ) { shouldAppend = jQuery( wrapper ).parent().parent().find( '.start_divider' ).length >= 2; } else if ( null !== wrapper.closest( '.start_divider' ) ) { shouldAppend = jQuery( wrapper ).closest( '.start_divider' ).parent().parent().find( '.start_divider' ).length >= 2; } if ( null !== wrapper.closest( '.frm-sortable-helper' ) ) { // avoid ever appending to the sortable helper. return; } if ( shouldAppend ) { // TODO instead of appendTo, we might need to look for the closest item, and appear above/below it. ui.placeholder.appendTo( wrapper ); } } function fixUnwrappedListItems() { document.querySelectorAll( 'ul.start_divider > li.form-field:not(.edit_field_type_end_divider)' ).forEach( function( field ) { wrapFieldLiInPlace( field ); } ); } function deleteEmptyDividerWrappers() { var dividers = document.querySelectorAll( 'ul.start_divider' ); if ( ! dividers.length ) { return; } dividers.forEach( function( divider ) { var children = [].slice.call( divider.children ); children.forEach( function( child ) { if ( 0 === child.children.length ) { child.remove(); } else if ( 1 === child.children.length && 'ul' === child.firstElementChild.nodeName.toLowerCase() && 0 === child.firstElementChild.children.length ) { child.remove(); } } ); } ); } /** * @returns {bool} true if the placeholder parent should be fixed. */ function shouldTryFixingPlaceholderParent( $placeholder ) { var closestSection = $placeholder.closest( '.start_divider' ); if ( null === closestSection ) { return false; } return jQuery( closestSection ).siblings( 'li.start_divider' ).length >= 1; } function getFieldsInRow( $row ) { return $row.children( 'li.form-field' ).not( '.ui-sortable-helper' ).not( '.edit_field_type_end_divider' ).filter( function() { return 'none' !== this.style.display; } ); } function determineIndexBasedOffOfMousePositionInRow( $row, x ) { var $inputs = getFieldsInRow( $row ), length = $inputs.length, index, input, inputLeft, returnIndex; returnIndex = 0; for ( index = length - 1; index >= 0; --index ) { input = $inputs.get( index ); inputLeft = jQuery( input ).offset().left; if ( x > inputLeft ) { returnIndex = index; if ( x > inputLeft + ( jQuery( input ).outerWidth() / 2 ) ) { returnIndex = index + 1; } break; } } return returnIndex; } function syncLayoutClasses( $item, type ) { var $fields, size, layoutClasses, classToAddFunction; if ( 'undefined' === typeof type ) { type = 'even'; } $fields = $item.parent().children( 'li.form-field, li.frmbutton_loadingnow' ).not( '.edit_field_type_end_divider' ); size = $fields.length; layoutClasses = getLayoutClasses(); if ( 'even' === type && 5 !== size ) { $fields.each( getSyncLayoutClass( layoutClasses, getEvenClassForSize( size ) ) ); } else if ( 'clear' === type ) { $fields.each( getSyncLayoutClass( layoutClasses, '' ) ); } else { if ( -1 !== [ 'left', 'right', 'middle', 'even' ].indexOf( type ) ) { classToAddFunction = function( index ) { return getClassForBlock( size, type, index ); }; } else { classToAddFunction = function( index ) { var size = type[ index ]; return getLayoutClassForSize( size ); }; } $fields.each( getSyncLayoutClass( layoutClasses, classToAddFunction ) ); } updateFieldGroupControls( $item.parent(), $fields.length ); } function updateFieldGroupControls( $row, count ) { var rowOffset, shouldShowControls, controls; rowOffset = $row.offset(); if ( 'undefined' === typeof rowOffset ) { return; } shouldShowControls = count >= 2; controls = document.getElementById( 'frm_field_group_controls' ); if ( null === controls ) { if ( ! shouldShowControls ) { // exit early. if we do not need controls and they do not exist, do nothing. return; } controls = div(); controls.id = 'frm_field_group_controls'; controls.setAttribute( 'role', 'group' ); controls.setAttribute( 'tabindex', 0 ); setFieldControlsHtml( controls ); document.getElementById( 'frm_builder_page' ).appendChild( controls ); } $row.append( controls ); controls.style.display = shouldShowControls ? 'block' : 'none'; } function setFieldControlsHtml( controls ) { var layoutOption, moveOption; layoutOption = document.createElement( 'span' ); layoutOption.innerHTML = ''; const layoutOptionLabel = __( 'Set Row Layout', 'formidable' ); addTooltip( layoutOption, layoutOptionLabel ); makeTabbable( layoutOption, layoutOptionLabel ); moveOption = document.createElement( 'span' ); moveOption.innerHTML = ''; moveOption.classList.add( 'frm-move' ); const moveOptionLabel = __( 'Move Field Group', 'formidable' ); addTooltip( moveOption, moveOptionLabel ); makeTabbable( moveOption, moveOptionLabel ); controls.innerHTML = ''; controls.appendChild( layoutOption ); controls.appendChild( moveOption ); controls.appendChild( getFieldControlsDropdown() ); } function addTooltip( element, title ) { element.setAttribute( 'data-toggle', 'tooltip' ); element.setAttribute( 'data-container', 'body' ); element.setAttribute( 'title', title ); element.addEventListener( 'mouseover', function() { if ( null === element.getAttribute( 'data-original-title' ) ) { jQuery( element ).tooltip(); } } ); } function getFieldControlsDropdown() { var dropdown, trigger, ul; dropdown = document.createElement( 'span' ); dropdown.classList.add( 'dropdown' ); trigger = document.createElement( 'a' ); trigger.classList.add( 'frm_bstooltip', 'frm-hover-icon', 'frm-dropdown-toggle', 'dropdown-toggle' ); trigger.setAttribute( 'title', __( 'More Options', 'formidable' ) ); trigger.setAttribute( 'data-toggle', 'dropdown' ); trigger.setAttribute( 'data-container', 'body' ); makeTabbable( trigger, __( 'More Options', 'formidable' ) ); trigger.innerHTML = ''; dropdown.appendChild( trigger ); ul = document.createElement( 'ul' ); ul.classList.add( 'frm-dropdown-menu' ); ul.setAttribute( 'role', 'menu' ); dropdown.appendChild( ul ); return dropdown; } function getSyncLayoutClass( layoutClasses, classToAdd ) { return function( itemIndex ) { var currentClassToAdd, length, layoutClassIndex, currentClass, activeLayoutClass, fieldId, layoutClassesInput; currentClassToAdd = 'function' === typeof classToAdd ? classToAdd( itemIndex ) : classToAdd; length = layoutClasses.length; activeLayoutClass = false; for ( layoutClassIndex = 0; layoutClassIndex < length; ++layoutClassIndex ) { currentClass = layoutClasses[ layoutClassIndex ]; if ( this.classList.contains( currentClass ) ) { activeLayoutClass = currentClass; break; } } fieldId = this.dataset.fid; if ( 'undefined' === typeof fieldId ) { // we are syncing the drag/drop placeholder before the actual field has loaded. // this will get called again afterward and the input will exist then. this.classList.add( currentClassToAdd ); return; } moveFieldSettings( document.getElementById( 'frm-single-settings-' + fieldId ) ); layoutClassesInput = document.getElementById( 'frm_classes_' + fieldId ); if ( null === layoutClassesInput ) { // not every field type has a layout class input. return; } if ( false === activeLayoutClass ) { if ( '' !== currentClassToAdd ) { layoutClassesInput.value = layoutClassesInput.value.concat( ' ' + currentClassToAdd ); } } else { this.classList.remove( activeLayoutClass ); layoutClassesInput.value = layoutClassesInput.value.replace( activeLayoutClass, currentClassToAdd ); } if ( this.classList.contains( 'frm_first' ) ) { this.classList.remove( 'frm_first' ); layoutClassesInput.value = layoutClassesInput.value.replace( 'frm_first', '' ).trim(); } if ( 0 === itemIndex ) { this.classList.add( 'frm_first' ); layoutClassesInput.value = layoutClassesInput.value.concat( ' frm_first' ); } jQuery( layoutClassesInput ).trigger( 'change' ); }; } function getLayoutClasses() { return [ 'frm_full', 'frm_half', 'frm_third', 'frm_fourth', 'frm_sixth', 'frm_two_thirds', 'frm_three_fourths', 'frm1', 'frm2', 'frm3', 'frm4', 'frm5', 'frm6', 'frm7', 'frm8', 'frm9', 'frm10', 'frm11', 'frm12' ]; } function setupFieldOptionSorting( sort ) { var opts = { items: '.frm_sortable_field_opts li', axis: 'y', opacity: 0.65, forcePlaceholderSize: false, handle: '.frm-drag', helper: function( e, li ) { copyHelper = li.clone().insertAfter( li ); return li.clone(); }, stop: function( e, ui ) { copyHelper && copyHelper.remove(); var fieldId = ui.item.attr( 'id' ).replace( 'frm_delete_field_', '' ).replace( '-' + ui.item.data( 'optkey' ) + '_container', '' ); resetDisplayedOpts( fieldId ); } }; jQuery( sort ).sortable( opts ); } // Get the section where a field is dropped function getSectionForFieldPlacement( currentItem ) { var section = ''; if ( typeof currentItem !== 'undefined' && ! currentItem.hasClass( 'edit_field_type_divider' ) ) { section = currentItem.closest( '.edit_field_type_divider' ); } return section; } // Get the form ID where a field is dropped function getFormIdForFieldPlacement( section ) { var formId = ''; if ( typeof section[0] !== 'undefined' ) { var sDivide = section.children( '.start_divider' ); sDivide.children( '.edit_field_type_end_divider' ).appendTo( sDivide ); if ( typeof section.attr( 'data-formid' ) !== 'undefined' ) { var fieldId = section.attr( 'data-fid' ); formId = jQuery( 'input[name="field_options[form_select_' + fieldId + ']"]' ).val(); } } if ( typeof formId === 'undefined' || formId === '' ) { formId = thisFormId; } return formId; } // Get the section ID where a field is dropped function getSectionIdForFieldPlacement( section ) { var sectionId = 0; if ( typeof section[0] !== 'undefined' ) { sectionId = section.attr( 'id' ).replace( 'frm_field_id_', '' ); } return sectionId; } /** * Update a field after it is dragged and dropped into, out of, or between sections * * @param {object} currentItem */ function updateFieldAfterMovingBetweenSections( currentItem ) { var fieldId, section, formId, sectionId; fieldId = currentItem.attr( 'id' ).replace( 'frm_field_id_', '' ); section = getSectionForFieldPlacement( currentItem ); formId = getFormIdForFieldPlacement( section ); sectionId = getSectionIdForFieldPlacement( section ); if ( currentItem.parent().hasClass( 'start_divider' ) ) { wrapFieldLiInPlace( currentItem ); } jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_update_field_after_move', form_id: formId, field: fieldId, section_id: sectionId, nonce: frmGlobal.nonce }, success: function() { toggleSectionHolder(); updateInSectionValue( fieldId, sectionId ); } }); } // Update the in_section field value function updateInSectionValue( fieldId, sectionId ) { document.getElementById( 'frm_in_section_' + fieldId ).value = sectionId; } /** * Add a new field by dragging and dropping it from the Fields sidebar * * @param {object} selectedItem * @param {object} fieldButton * @param {object} opts */ function insertNewFieldByDragging( selectedItem, fieldButton ) { var fieldType, addBtn, sortableData, currentItem, insertAtIndex, section, formId, sectionId, loadingID, hasBreak, $placeholder; fieldType = fieldButton.attr( 'id' ); // We'll optimistically disable the button now. We'll re-enable if AJAX fails if ( 'summary' === fieldType ) { addBtn = fieldButton.children( '.frm_add_field' ); disableSummaryBtnBeforeAJAX( addBtn, fieldButton ); } sortableData = jQuery( selectedItem ).data().uiSortable; currentItem = sortableData.currentItem; insertAtIndex = determineIndexBasedOffOfMousePositionInRow( currentItem.parent(), currentItem.offset().left ); jQuery( getFieldsInRow( currentItem.parent() ).get( insertAtIndex ) ).before( currentItem ); section = getSectionForFieldPlacement( currentItem ); formId = getFormIdForFieldPlacement( section ); sectionId = getSectionIdForFieldPlacement( section ); loadingID = fieldType.replace( '|', '-' ) + '_' + getAutoId(); $placeholder = jQuery( '
  • ' ); currentItem.replaceWith( $placeholder ); syncLayoutClasses( $placeholder ); hasBreak = 0; if ( 'summary' === fieldType ) { // see if we need to insert a page break before this newly-added summary field. Check for at least 1 page break hasBreak = jQuery( '.frmbutton_loadingnow#' + loadingID ).prevAll( 'li[data-type="break"]' ).length ? 1 : 0; } jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_insert_field', form_id: formId, field_type: fieldType, section_id: sectionId, nonce: frmGlobal.nonce, has_break: hasBreak }, success: function( msg ) { var $siblings, replaceWith; document.getElementById( 'frm_form_editor_container' ).classList.add( 'frm-has-fields' ); $siblings = $placeholder.siblings( 'li.form-field' ).not( '.edit_field_type_end_divider' ); if ( ! $siblings.length ) { // if dragging into a new row, we need to wrap the li first. replaceWith = wrapFieldLi( msg ); } else { replaceWith = msg; } $placeholder.replaceWith( replaceWith ); updateFieldOrder(); afterAddField( msg, false ); if ( $siblings.length ) { syncLayoutClasses( $siblings.first() ); } toggleSectionHolder(); }, error: function( jqXHR, textStatus, errorThrown ) { maybeReenableSummaryBtnAfterAJAX( fieldType, addBtn, fieldButton, errorThrown ); } }); } /** * Get a unique id that automatically increments with every function call. * Can be used for any UI that requires a unique id. * Not to be used in data. * * @returns {integer} */ function getAutoId() { return ++autoId; } // don't allow page break, embed form, or section inside section field // don't allow page breaks inside of field groups. // don't allow field groups with sections inside of sections. // don't allow field groups in field groups. // don't allow hidden fields inside of field groups but allow them in sections. function allowDrop( ui ) { var fieldsInRow, insideFieldGroup, insideSection, isNewField, isPageBreak, isFieldGroup, isSection; fieldsInRow = getFieldsInRow( ui.placeholder.parent() ); if ( ! groupCanFitAnotherField( fieldsInRow, ui.item ) ) { return false; } insideFieldGroup = fieldsInRow.length > 0; insideSection = ui.placeholder.closest( '.start_divider' ).length > 0; if ( ! insideSection && ! insideFieldGroup ) { return true; } if ( insideFieldGroup && ui.placeholder.siblings( '.edit_field_type_break, .edit_field_type_hidden' ).length ) { // never allow any field beside a page break or a hidden field. return false; } if ( insideSection && ui.placeholder.siblings().length > 1 && ui.placeholder.prev().hasClass( 'edit_field_type_end_divider' ) ) { return false; } isNewField = ui.item.hasClass( 'frmbutton' ); if ( isNewField ) { isPageBreak = ui.item.hasClass( 'frm_tbreak' ); if ( isPageBreak ) { // do not allow page break in both sections and field groups. return false; } if ( insideFieldGroup && ( ui.item.hasClass( 'frm_thidden' ) || ui.item.hasClass( 'frm_tsummary' ) ) ) { // do not allow a hidden field or summary field in a field group. return false; } if ( ! insideSection ) { return true; } return ! ui.item.hasClass( 'frm_tform' ) && ! ui.item.hasClass( 'frm_tdivider' ) && ! ui.item.hasClass( 'frm_tdivider-repeat' ); } isPageBreak = ui.item.hasClass( 'edit_field_type_break' ); if ( isPageBreak ) { // do not allow page break in both sections and field groups. return false; } isFieldGroup = ui.item.find( 'ul.frm_sorting' ).length > 0; isSection = ui.item.hasClass( 'edit_field_type_divider' ); if ( insideSection && isSection ) { // but do not allow a section inside of a section. return false; } if ( isFieldGroup && insideFieldGroup ) { // allow a field group inside of a field group if it is being placed within a section above/below another field group. return insideSection && ui.placeholder.siblings( 'li.edit_field_type_end_divider' ).length > 0; } if ( insideFieldGroup && ui.item.hasClass( 'edit_field_type_hidden' ) ) { // do not allow a hidden field inside of a field group. return false; } if ( ! insideSection ) { return true; } if ( ui.item.find( '.edit_field_type_divider' ).length ) { // if we are dragging a field group with a section, do not allow it in section. return false; } // moving an existing field return ! ui.item.hasClass( 'edit_field_type_form' ) && ! isSection; } function groupCanFitAnotherField( fieldsInRow, $field ) { var fieldId; if ( fieldsInRow.length < 6 ) { return true; } if ( fieldsInRow.length > 6 ) { return false; } fieldId = $field.attr( 'data-fid' ); // allow 6 if we're not changing field groups. return 1 === jQuery( fieldsInRow ).filter( '[data-fid="' + fieldId + '"]' ).length; } function loadFields( fieldId ) { var addHtmlToField, nextElement, thisField = document.getElementById( fieldId ), $thisField = jQuery( thisField ), field = []; addHtmlToField = function( element ) { var frmHiddenFdata = element.querySelector( '.frm_hidden_fdata' ); element.classList.add( 'frm_load_now' ); if ( frmHiddenFdata !== null ) { field.push( frmHiddenFdata.innerHTML ); } }; nextElement = thisField; addHtmlToField( nextElement ); while ( nextElement.nextElementSibling && field.length < 15 ) { addHtmlToField( nextElement.nextElementSibling ); nextElement = nextElement.nextElementSibling; } jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_load_field', field: field, form_id: thisFormId, nonce: frmGlobal.nonce }, success: function( html ) { var key, $nextSet; html = html.replace( /^\s+|\s+$/g, '' ); if ( html.indexOf( '{' ) !== 0 ) { jQuery( '.frm_load_now' ).removeClass( '.frm_load_now' ).html( 'Error' ); return; } html = JSON.parse( html ); for ( key in html ) { jQuery( '#frm_field_id_' + key ).replaceWith( html[key]); setupSortable( '#frm_field_id_' + key + '.edit_field_type_divider ul.frm_sorting' ); } $nextSet = $thisField.nextAll( '.frm_field_loading:not(.frm_load_now)' ); if ( $nextSet.length ) { loadFields( $nextSet.attr( 'id' ) ); } else { // go up a level $nextSet = jQuery( document.getElementById( 'frm-show-fields' ) ).find( '.frm_field_loading:not(.frm_load_now)' ); if ( $nextSet.length ) { loadFields( $nextSet.attr( 'id' ) ); } } initiateMultiselect(); renumberPageBreaks(); maybeHideQuantityProductFieldOption(); } }); } function addFieldClick() { /*jshint validthis:true */ var $thisObj = jQuery( this ); // there is no real way to disable a (with a valid href attribute) in HTML - https://css-tricks.com/how-to-disable-links/ if ( $thisObj.hasClass( 'disabled' ) ) { return false; } var $button = $thisObj.closest( '.frmbutton' ); var fieldType = $button.attr( 'id' ); var hasBreak = 0; if ( 'summary' === fieldType ) { // We'll optimistically disable $button now. We'll re-enable if AJAX fails disableSummaryBtnBeforeAJAX( $thisObj, $button ); hasBreak = $newFields.children( 'li[data-type="break"]' ).length > 0 ? 1 : 0; } var formId = thisFormId; jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_insert_field', form_id: formId, field_type: fieldType, section_id: 0, nonce: frmGlobal.nonce, has_break: hasBreak }, success: function( msg ) { document.getElementById( 'frm_form_editor_container' ).classList.add( 'frm-has-fields' ); $newFields.append( wrapFieldLi( msg ) ); afterAddField( msg, true ); }, error: function( jqXHR, textStatus, errorThrown ) { maybeReenableSummaryBtnAfterAJAX( fieldType, $thisObj, $button, errorThrown ); } }); return false; } function disableSummaryBtnBeforeAJAX( addBtn, fieldButton ) { addBtn.addClass( 'disabled' ); fieldButton.draggable( 'disable' ); } function reenableAddSummaryBtn() { var frmBtn = jQuery( 'li#summary' ); var addFieldLink = frmBtn.children( '.frm_add_field' ); frmBtn.draggable( 'enable' ); addFieldLink.removeClass( 'disabled' ); } function maybeDisableAddSummaryBtn() { var summary = document.getElementById( 'summary' ); if ( summary && ! summary.classList.contains( 'frm_show_upgrade' ) && formHasSummaryField() ) { disableAddSummaryBtn(); } } function disableAddSummaryBtn() { var frmBtn = jQuery( 'li#summary' ); var addFieldLink = frmBtn.children( '.frm_add_field' ); frmBtn.draggable( 'disable' ); addFieldLink.addClass( 'disabled' ); } function maybeReenableSummaryBtnAfterAJAX( fieldType, addBtn, fieldButton, errorThrown ) { infoModal( errorThrown + '. Please try again.' ); if ( 'summary' === fieldType ) { addBtn.removeClass( 'disabled' ); fieldButton.draggable( 'enable' ); } } function formHasSummaryField() { // .edit_field_type_summary is a better selector here in order to also cover fields loaded by AJAX return $newFields.children( 'li.edit_field_type_summary' ).length > 0; } function maybeHideQuantityProductFieldOption() { var hide = true, opts = document.querySelectorAll( '.frmjs_prod_field_opt_cont' ); if ( $newFields.find( 'li.edit_field_type_product' ).length > 1 ) { hide = false; } for ( var i = 0; i < opts.length; i++ ) { if ( hide ) { opts[ i ].classList.add( 'frm_hidden' ); } else { opts[ i ].classList.remove( 'frm_hidden' ); } } } function duplicateField() { var $field, fieldId, children, newRowId, fieldOrder; $field = jQuery( this ).closest( 'li.form-field' ); if ( $field.hasClass( 'frm-section-collapsed' ) || $field.hasClass( 'frm-page-collapsed' ) ) { return false; } closeOpenFieldDropdowns(); fieldId = $field.data( 'fid' ); children = fieldsInSection( fieldId ); newRowId = this.getAttribute( 'frm-target-row-id' ); if ( null !== newRowId ) { fieldOrder = this.getAttribute( 'frm-field-order' ); } jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_duplicate_field', field_id: fieldId, form_id: thisFormId, children: children, nonce: frmGlobal.nonce }, success: function( msg ) { var newRow; if ( null !== newRowId ) { newRow = document.getElementById( newRowId ); if ( null !== newRow ) { jQuery( newRow ).append( msg ); if ( null !== fieldOrder ) { newRow.lastElementChild.setAttribute( 'frm-field-order', fieldOrder ); } jQuery( newRow ).trigger( 'frm_added_duplicated_field_to_row', { duplicatedFieldHtml: msg, originalFieldId: fieldId } ); afterAddField( msg, false ); return; } } if ( $field.siblings( 'li.form-field' ).length ) { $field.after( msg ); syncLayoutClasses( $field ); } else { $field.parent().parent().after( wrapFieldLi( msg ) ); } updateFieldOrder(); afterAddField( msg, false ); maybeDuplicateUnsavedSettings( fieldId, msg ); } }); return false; } function maybeDuplicateUnsavedSettings( originalFieldId, newFieldHtml ) { var originalSettings, newFieldId, copySettings, fieldOptionKeys, originalDefault, copyDefault; originalSettings = document.getElementById( 'frm-single-settings-' + originalFieldId ); if ( null === originalSettings ) { return; } newFieldId = jQuery( newFieldHtml ).attr( 'data-fid' ); if ( 'undefined' === typeof newFieldId ) { return; } copySettings = document.getElementById( 'frm-single-settings-' + newFieldId ); if ( null === copySettings ) { return; } fieldOptionKeys = [ 'name', 'required', 'unique', 'read_only', 'placeholder', 'description', 'size', 'max', 'format', 'prepend', 'append', 'separate_value' ]; originalSettings.querySelectorAll( 'input[name^="field_options["], textarea[name^="field_options["]' ).forEach( function( originalSetting ) { var key, tagType, copySetting; key = getKeyFromSettingInput( originalSetting ); if ( 'options' === key ) { copyOption( originalSetting, copySettings, originalFieldId, newFieldId ); return; } if ( -1 === fieldOptionKeys.indexOf( key ) ) { return; } tagType = originalSetting.matches( 'input' ) ? 'input' : 'textarea'; copySetting = copySettings.querySelector( tagType + '[name="field_options[' + key + '_' + newFieldId + ']"]' ); if ( null === copySetting ) { return; } if ( 'checkbox' === originalSetting.type ) { if ( originalSetting.checked !== copySetting.checked ) { jQuery( copySetting ).trigger( 'click' ); } } else if ( 'text' === originalSetting.type || 'textarea' === tagType ) { if ( originalSetting.value !== copySetting.value ) { copySetting.value = originalSetting.value; jQuery( copySetting ).trigger( 'change' ); } } } ); originalDefault = originalSettings.querySelector( 'input[name="default_value_' + originalFieldId + '"]' ); if ( null !== originalDefault ) { copyDefault = copySettings.querySelector( 'input[name="default_value_' + newFieldId + '"]' ); if ( null !== copyDefault && originalDefault.value !== copyDefault.value ) { copyDefault.value = originalDefault.value; jQuery( copyDefault ).trigger( 'change' ); } } } function copyOption( originalSetting, copySettings, originalFieldId, newFieldId ) { var remainingKeyDetails, copyKey, copySetting; remainingKeyDetails = originalSetting.name.substr( 23 + ( '' + originalFieldId ).length ); copyKey = 'field_options[options_' + newFieldId + ']' + remainingKeyDetails; copySetting = copySettings.querySelector( 'input[name="' + copyKey + '"]' ); if ( null !== copySetting && copySetting.value !== originalSetting.value ) { copySetting.value = originalSetting.value; jQuery( copySetting ).trigger( 'change' ); } } function getKeyFromSettingInput( input ) { var nameWithoutPrefix, nameSplit; nameWithoutPrefix = input.name.substr( 14 ); nameSplit = nameWithoutPrefix.split( '_' ); nameSplit.pop(); return nameSplit.join( '_' ); } function closeOpenFieldDropdowns() { var openSettings = document.querySelector( '.frm-field-settings-open' ); if ( null !== openSettings ) { openSettings.classList.remove( 'frm-field-settings-open' ); jQuery( document ).off( 'click', '#frm_builder_page', handleClickOutsideOfFieldSettings ); jQuery( '.frm-field-action-icons .dropdown.open' ).removeClass( 'open' ); } } function handleClickOutsideOfFieldSettings( event ) { if ( ! jQuery( event.originalEvent.target ).closest( '.frm-field-action-icons' ).length ) { closeOpenFieldDropdowns(); } } function checkForMultiselectKeysOnMouseMove( event ) { var keyIsDown = ! ! ( event.ctrlKey || event.metaKey || event.shiftKey ); jQuery( document.getElementById( 'frm_builder_page' ) ).toggleClass( 'frm-multiselect-key-is-down', keyIsDown ); checkForActiveHoverTarget( event ); } function checkForActiveHoverTarget( event ) { var container, elementFromPoint, list, previousHoverTarget; container = document.getElementById( 'post-body-content' ); if ( container.classList.contains( 'frm-dragging-field' ) ) { return; } if ( null !== document.querySelector( '.frm-field-group-hover-target .frm-field-settings-open' ) ) { // do not set a hover target if a dropdown is open for the current hover target. return; } elementFromPoint = document.elementFromPoint( event.clientX, event.clientY ); if ( null !== elementFromPoint && ! elementFromPoint.classList.contains( 'edit_field_type_divider' ) ) { list = elementFromPoint.closest( 'ul.frm_sorting' ); if ( null !== list && ! list.classList.contains( 'start_divider' ) && 'frm-show-fields' !== list.id ) { previousHoverTarget = maybeRemoveGroupHoverTarget(); if ( false !== previousHoverTarget && ! jQuery( previousHoverTarget ).is( list ) ) { destroyFieldGroupPopup(); } updateFieldGroupControls( jQuery( list ), getFieldsInRow( jQuery( list ) ).length ); list.classList.add( 'frm-field-group-hover-target' ); jQuery( '#wpbody-content' ).on( 'mousemove', maybeRemoveHoverTargetOnMouseMove ); } } } function maybeRemoveGroupHoverTarget() { var controls, previousHoverTarget; controls = document.getElementById( 'frm_field_group_controls' ); if ( null !== controls ) { controls.style.display = 'none'; } previousHoverTarget = document.querySelector( '.frm-field-group-hover-target' ); if ( null === previousHoverTarget ) { return false; } jQuery( '#wpbody-content' ).off( 'mousemove', maybeRemoveHoverTargetOnMouseMove ); previousHoverTarget.classList.remove( 'frm-field-group-hover-target' ); return previousHoverTarget; } function maybeRemoveHoverTargetOnMouseMove( event ) { var elementFromPoint = document.elementFromPoint( event.clientX, event.clientY ); if ( null !== elementFromPoint && null !== elementFromPoint.closest( '#frm-show-fields' ) ) { return; } maybeRemoveGroupHoverTarget(); } function onFieldActionDropdownShow( isFieldGroup ) { unselectFieldGroups(); // maybe offset the dropdown if it goes off of the right of the screen. setTimeout( function() { var ul, $ul; ul = document.querySelector( '.dropdown.open ul' ); if ( null === ul ) { return; } if ( null === ul.getAttribute( 'aria-label' ) ) { ul.setAttribute( 'aria-label', __( 'More Options', 'formidable' ) ); } if ( 0 === ul.children.length ) { fillFieldActionDropdown( ul, true === isFieldGroup ); } $ul = jQuery( ul ); if ( $ul.offset().left > jQuery( window ).width() - $ul.outerWidth() ) { ul.style.left = ( -$ul.outerWidth() ) + 'px'; } const firstAnchor = ul.firstElementChild.querySelector( 'a' ); if ( firstAnchor ) { firstAnchor.focus(); } }, 0 ); } function onFieldGroupActionDropdownShow() { onFieldActionDropdownShow( true ); } function fillFieldActionDropdown( ul, isFieldGroup ) { var classSuffix, options; classSuffix = isFieldGroup ? '_field_group' : '_field'; options = [ getDeleteActionOption( isFieldGroup ), getDuplicateActionOption( isFieldGroup ) ]; if ( ! isFieldGroup ) { options.push( { class: 'frm_select', icon: 'frm_settings_icon', label: __( 'Field settings', 'formidable' ) } ); } options.forEach( function( option ) { var li, anchor, span; li = document.createElement( 'li' ); li.classList.add( 'frm_dropdown_li', 'frm_more_options_li' ); anchor = document.createElement( 'a' ); anchor.classList.add( option.class + classSuffix ); anchor.setAttribute( 'href', '#' ); makeTabbable( anchor ); span = document.createElement( 'span' ); span.textContent = option.label; anchor.innerHTML = ''; anchor.appendChild( document.createTextNode( ' ' ) ); anchor.appendChild( span ); li.appendChild( anchor ); ul.appendChild( li ); } ); } function getDeleteActionOption( isFieldGroup ) { var option = { class: 'frm_delete', icon: 'frm_delete_icon' }; option.label = isFieldGroup ? __( 'Delete Group', 'formidable' ) : __( 'Delete', 'formidable' ); return option; } function getDuplicateActionOption( isFieldGroup ) { var option = { class: 'frm_clone', icon: 'frm_clone_icon' }; option.label = isFieldGroup ? __( 'Duplicate Group', 'formidable' ) : __( 'Duplicate', 'formidable' ); return option; } function wrapFieldLi( li ) { return jQuery( '
  • ' ) .addClass( 'frm_field_box' ) .html( jQuery( '