/home/altere25/infinet.finance/wp-content/plugins/formidable/js
NameSizeModeActions
admin/-0755rm
codemirror/-0755rm
ac.js85840644editdlrm
bootstrap-multiselect.js812720644editdlrm
bootstrap.min.js624410644editdlrm
formidable.js501470644editdlrm
formidable.min.js357390644editdlrm
formidable_admin.js3207070644editdlrm
formidable_admin_global.js95140644editdlrm
formidable_blocks.js144880644editdlrm
frm.min.js357400644editdlrm
plugin-search.js21550644editdlrm
popper.min.js212580644editdlrm
Edit: /home/altere25/infinet.finance/wp-content/plugins/formidable/js/formidable_admin.js (320707B)
/* 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, fromDom */ const { tag, div, span, a, svg, img } = frmDom; const { doJsonFetch } = frmDom.ajax; const icons = { save: svg({ href: '#frm_save_icon' }), drag: svg({ href: '#frm_drag_icon', classList: [ 'frm_drag_icon', 'frm-drag' ] }) }; let $newFields = jQuery( document.getElementById( 'frm-show-fields' ) ), builderForm = document.getElementById( 'new_fields' ), thisForm = document.getElementById( 'form_id' ), copyHelper = false, fieldsUpdated = 0, thisFormId = 0, autoId = 0, optionMap = {}, lastNewActionIdReturned = 0; const { __ } = wp.i18n; let debouncedSyncAfterDragAndDrop, postBodyContent, $postBodyContent; 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 verify, $confirmMessage, i, dataAtts, btnClass, $info = initModal( '#frm_confirm_modal', '400px' ), continueButton = document.getElementById( 'frm-confirmed-click' ); if ( $info === false ) { return false; } verify = link.getAttribute( 'data-frmverify' ); btnClass = verify ? link.getAttribute( 'data-frmverify-btn' ) : ''; $confirmMessage = jQuery( '.frm-confirm-msg' ); $confirmMessage.empty(); if ( verify ) { $confirmMessage.append( document.createTextNode( verify ) ); if ( btnClass ) { continueButton.classList.add( btnClass ); } } 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; } /** * Toggle a class on target elements when an anchor is clicked, or when a radio or checkbox has been selected. * * @param {Event} e Event with either the change or click type. * @returns {false} */ function hideShowItem( e ) { /*jshint validthis:true */ let hide = this.getAttribute( 'data-frmhide' ); let show = this.getAttribute( 'data-frmshow' ); // Flip unchecked checkboxes so an off value undoes the on value. if ( isUncheckedCheckbox( this ) ) { if ( hide !== null ) { show = hide; hide = null; } else if ( show !== null ) { hide = show; show = null; } } e.preventDefault(); const toggleClass = this.getAttribute( 'data-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 isUncheckedCheckbox( element ) { return 'INPUT' === element.nodeName && 'checkbox' === element.type && ! element.checked; } 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( 'change', 'input[data-frmhide], input[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 */ let show, hide, removeMore; if ( parseInt( this.getAttribute( 'data-skip-frm-js' ) ) || confirmLinkClick( this ) === false ) { return; } const deleteButton = jQuery( this ); const id = deleteButton.attr( 'data-removeid' ); show = deleteButton.attr( 'data-showlast' ); if ( typeof show === 'undefined' ) { show = ''; } hide = deleteButton.attr( 'data-hidelast' ); if ( typeof hide === 'undefined' ) { hide = ''; } removeMore = deleteButton.attr( 'data-removemore' ); 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'; } } const $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' ); } if ( this.closest( '.frm_form_action_settings' ) ) { const type = this.closest( '.frm_form_action_settings' ).querySelector( '.frm_action_name' ).value; afterActionRemoved( 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 afterActionRemoved( type ) { checkActiveAction( type ); const hookName = 'frm_after_action_removed'; const hookArgs = { type }; wp.hooks.doAction( hookName, hookArgs ); } function clickWidget( event, b ) { /*jshint validthis:true */ if ( typeof b === 'undefined' ) { b = this; } popCalcFields( b, false ); const cont = jQuery( b ).closest( '.frm_form_action_settings' ); const target = event.target; if ( cont.length && typeof target !== 'undefined' ) { const 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; } } } let inside = cont.children( '.widget-inside' ); if ( cont.length && inside.find( 'p, div, table' ).length < 1 ) { const actionId = cont.find( 'input[name$="[ID]"]' ).val(); const 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' ) ); frmDom.autocomplete.initAutocomplete( 'page', inside ); jQuery( b ).trigger( 'frm-action-loaded' ); /** * Fires after filling form action content when opening. * * @since 5.5.4 * * @param {Object} insideElement JQuery object of form action inside element. */ wp.hooks.doAction( 'frm_filled_form_action', inside ); } }); } } 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( '#', '' ) ); } } function setupSortable( sortableSelector ) { document.querySelectorAll( sortableSelector ).forEach( list => { makeDroppable( list ); Array.from( list.children ).forEach( child => makeDraggable( child, '.frm-move' ) ); const $sectionTitle = jQuery( list ).children( '[data-type="divider"]' ).children( '.divider_section_only' ); if ( $sectionTitle.length ) { makeDroppable( $sectionTitle ); } } ); setupFieldOptionSorting( jQuery( '#frm_builder_page' ) ); } function makeDroppable( list ) { jQuery( list ).droppable({ accept: '.frmbutton, li.frm_field_box', deactivate: handleFieldDrop, over: onDragOverDroppable, out: onDraggableLeavesDroppable, tolerance: 'pointer' }); } function onDragOverDroppable( event, ui ) { const droppable = getDroppableForOnDragOver( event.target ); const draggable = ui.draggable[0]; if ( ! allowDrop( draggable, droppable ) ) { droppable.classList.remove( 'frm-over-droppable' ); jQuery( droppable ).parents( 'ul.frm_sorting' ).addClass( 'frm-over-droppable' ); return; } document.querySelectorAll( '.frm-over-droppable' ).forEach( droppable => droppable.classList.remove( 'frm-over-droppable' ) ); droppable.classList.add( 'frm-over-droppable' ); jQuery( droppable ).parents( 'ul.frm_sorting' ).addClass( 'frm-over-droppable' ); } /** * Maybe change the droppable. * Section titles are made droppable, but are not a list, so we need to change the droppable to the section's list instead. * * @param {Element} droppable * @returns {Element} */ function getDroppableForOnDragOver( droppable ) { if ( droppable.classList.contains( 'divider_section_only' ) ) { droppable = jQuery( droppable ).nextAll( '.start_divider.frm_sorting' ).get( 0 ); } return droppable; } function onDraggableLeavesDroppable( event ) { const droppable = event.target; droppable.classList.remove( 'frm-over-droppable' ); } function makeDraggable( draggable, handle ) { const settings = { helper: getDraggableHelper, revert: 'invalid', delay: 10, start: handleDragStart, stop: handleDragStop, drag: handleDrag, cursor: 'grabbing', refreshPositions: true, cursorAt: { top: 0, left: 90 // The width of draggable button is 180. 90 should center the draggable on the cursor. } }; if ( 'string' === typeof handle ) { settings.handle = handle; } jQuery( draggable ).draggable( settings ); } function getDraggableHelper( event ) { const draggable = event.delegateTarget; if ( isFieldGroup( draggable ) ) { const newTextFieldClone = document.getElementById( 'frm-insert-fields' ).querySelector( '.frm_ttext' ).cloneNode( true ); newTextFieldClone.querySelector( 'use' ).setAttributeNS( 'http://www.w3.org/1999/xlink', 'href', '#frm_field_group_layout_icon' ); newTextFieldClone.querySelector( 'span' ).textContent = __( 'Field Group' ); newTextFieldClone.classList.add( 'frm_field_box' ); newTextFieldClone.classList.add( 'ui-sortable-helper' ); return newTextFieldClone; } let copyTarget; const isNewField = draggable.classList.contains( 'frmbutton' ); if ( isNewField ) { copyTarget = draggable.cloneNode( true ); copyTarget.classList.add( 'ui-sortable-helper' ); draggable.classList.add( 'frm-new-field' ); return copyTarget; } if ( draggable.hasAttribute( 'data-ftype' ) ) { const fieldType = draggable.getAttribute( 'data-ftype' ); copyTarget = document.getElementById( 'frm-insert-fields' ).querySelector( '.frm_t' + fieldType ); copyTarget = copyTarget.cloneNode( true ); copyTarget.classList.add( 'form-field' ); copyTarget.classList.add( 'ui-sortable-helper' ); if ( copyTarget ) { return copyTarget.cloneNode( true ); } } return div({ className: 'frmbutton' }); } function handleDragStart( event, ui ) { const container = postBodyContent; container.classList.add( 'frm-dragging-field' ); document.body.classList.add( 'frm-dragging' ); ui.helper.addClass( 'frm-sortable-helper' ); ui.helper.initialOffset = container.scrollTop; event.target.classList.add( 'frm-drag-fade' ); unselectFieldGroups(); deleteEmptyDividerWrappers(); maybeRemoveGroupHoverTarget(); closeOpenFieldDropdowns(); deleteTooltips(); } function handleDragStop() { const container = postBodyContent; container.classList.remove( 'frm-dragging-field' ); document.body.classList.remove( 'frm-dragging' ); const fade = document.querySelector( '.frm-drag-fade' ); if ( fade ) { fade.classList.remove( 'frm-drag-fade' ); } } function handleDrag( event, ui ) { maybeScrollBuilder( event ); const draggable = event.target; const droppable = getDroppableTarget(); let placeholder = document.getElementById( 'frm_drag_placeholder' ); if ( ! allowDrop( draggable, droppable ) ) { if ( placeholder ) { placeholder.remove(); } return; } if ( ! placeholder ) { placeholder = tag( 'li', { id: 'frm_drag_placeholder', className: 'sortable-placeholder' }); } const frmSortableHelper = ui.helper.get( 0 ); if ( frmSortableHelper.classList.contains( 'form-field' ) || frmSortableHelper.classList.contains( 'frm_field_box' ) ) { // Sync the y position of the draggable so it still follows the cursor after scrolling up and down the field list. frmSortableHelper.style.transform = 'translateY(' + getDragOffset( ui.helper ) + 'px)'; } if ( 'frm-show-fields' === droppable.id || droppable.classList.contains( 'start_divider' ) ) { placeholder.style.left = 0; handleDragOverYAxis({ droppable, y: event.clientY, placeholder }); return; } placeholder.style.top = ''; handleDragOverFieldGroup({ droppable, x: event.clientX, placeholder }); } function maybeScrollBuilder( event ) { $postBodyContent.scrollTop( ( _, v ) => { const moved = event.clientY; const h = postBodyContent.offsetHeight; const relativePos = event.clientY - postBodyContent.offsetTop; const y = relativePos - h / 2; if ( relativePos > ( h - 50 ) && moved > 5 ) { // Scrolling down. return v + y * 0.1; } if ( relativePos < 70 && moved < 130 ) { // Scrolling up. return v - Math.abs( y * 0.1 ); } return v; } ); } function getDragOffset( $helper ) { return postBodyContent.scrollTop - $helper.initialOffset; } function getDroppableTarget() { let droppable = document.getElementById( 'frm-show-fields' ); while ( droppable.querySelector( '.frm-over-droppable' ) ) { droppable = droppable.querySelector( '.frm-over-droppable' ); } if ( 'frm-show-fields' === droppable.id && ! droppable.classList.contains( 'frm-over-droppable' ) ) { droppable = false; } return droppable; } function handleFieldDrop( _, ui ) { const draggable = ui.draggable[0]; const placeholder = document.getElementById( 'frm_drag_placeholder' ); if ( ! placeholder ) { ui.helper.remove(); debouncedSyncAfterDragAndDrop(); return; } maybeOpenCollapsedPage( placeholder ); const $previousFieldContainer = ui.helper.parent(); const previousSection = ui.helper.get( 0 ).closest( 'ul.start_divider' ); const newSection = placeholder.closest( 'ul.frm_sorting' ); if ( draggable.classList.contains( 'frm-new-field' ) ) { insertNewFieldByDragging( draggable.id ); } else { moveFieldThatAlreadyExists( draggable, placeholder ); } const previousSectionId = previousSection ? parseInt( previousSection.closest( '.edit_field_type_divider' ).getAttribute( 'data-fid' ) ) : 0; const newSectionId = newSection.classList.contains( 'start_divider' ) ? parseInt( newSection.closest( '.edit_field_type_divider' ).getAttribute( 'data-fid' ) ) : 0; placeholder.remove(); ui.helper.remove(); const $previousContainerFields = $previousFieldContainer.length ? getFieldsInRow( $previousFieldContainer ) : []; maybeUpdatePreviousFieldContainerAfterDrop( $previousFieldContainer, $previousContainerFields ); maybeUpdateDraggableClassAfterDrop( draggable, $previousContainerFields ); if ( previousSectionId !== newSectionId ) { updateFieldAfterMovingBetweenSections( jQuery( draggable ), previousSection ); } debouncedSyncAfterDragAndDrop(); } /** * If a page if collapsed, expand it before dragging since only the page break will move. * * @param {Element} placeholder * @returns {void} */ function maybeOpenCollapsedPage( placeholder ) { if ( ! placeholder.previousElementSibling || ! placeholder.previousElementSibling.classList.contains( 'frm-is-collapsed' ) ) { return; } const $pageBreakField = jQuery( placeholder ).prevUntil( '[data-type="break"]' ); if ( ! $pageBreakField.length ) { return; } const collapseButton = $pageBreakField.find( '.frm-collapse-page' ).get( 0 ); if ( collapseButton ) { collapseButton.click(); } } function maybeUpdatePreviousFieldContainerAfterDrop( $previousFieldContainer, $previousContainerFields ) { if ( ! $previousFieldContainer.length ) { return; } if ( $previousContainerFields.length ) { syncLayoutClasses( $previousContainerFields.first() ); } else { maybeDeleteAnEmptyFieldGroup( $previousFieldContainer.get( 0 ) ); } } function maybeUpdateDraggableClassAfterDrop( draggable, $previousContainerFields ) { if ( 0 !== $previousContainerFields.length || 1 !== getFieldsInRow( jQuery( draggable.parentNode ) ).length ) { syncLayoutClasses( jQuery( draggable ) ); } } /** * Remove an empty field group, but don't remove an empty section. * * @param {Element} previousFieldContainer * @returns {void} */ function maybeDeleteAnEmptyFieldGroup( previousFieldContainer ) { const closestFieldBox = previousFieldContainer.closest( 'li.frm_field_box' ); if ( closestFieldBox && ! closestFieldBox.classList.contains( 'edit_field_type_divider' ) ) { closestFieldBox.remove(); } } function handleDragOverYAxis({ droppable, y, placeholder }) { const $list = jQuery( droppable ); let top; $children = $list.children().not( '.edit_field_type_end_divider' ); if ( 0 === $children.length ) { $list.prepend( placeholder ); top = 0; } else { const insertAtIndex = determineIndexBasedOffOfMousePositionInList( $list, y ); if ( insertAtIndex === $children.length ) { const $lastChild = jQuery( $children.get( insertAtIndex - 1 ) ); top = $lastChild.offset().top + $lastChild.outerHeight(); $list.append( placeholder ); // Make sure nothing gets inserted after the end divider. const $endDivider = $list.children( '.edit_field_type_end_divider' ); if ( $endDivider.length ) { $list.append( $endDivider ); } } else { top = jQuery( $children.get( insertAtIndex ) ).offset().top; jQuery( $children.get( insertAtIndex ) ).before( placeholder ); } } top -= $list.offset().top; placeholder.style.top = top + 'px'; } function determineIndexBasedOffOfMousePositionInList( $list, y ) { const $items = $list.children().not( '.edit_field_type_end_divider' ); const length = $items.length; let index, item, itemTop, returnIndex; returnIndex = 0; for ( index = length - 1; index >= 0; --index ) { item = $items.get( index ); itemTop = jQuery( item ).offset().top; if ( y > itemTop ) { returnIndex = index; if ( y > itemTop + ( jQuery( item ).outerHeight() / 2 ) ) { returnIndex = index + 1; } break; } } return returnIndex; } function handleDragOverFieldGroup({ droppable, x, placeholder }) { const $row = jQuery( droppable ); const $children = getFieldsInRow( $row ); if ( ! $children.length ) { return; } let left; const insertAtIndex = determineIndexBasedOffOfMousePositionInRow( $row, x ); if ( insertAtIndex === $children.length ) { const $lastChild = jQuery( $children.get( insertAtIndex - 1 ) ); left = $lastChild.offset().left + $lastChild.outerWidth(); $row.append( placeholder ); } else { left = jQuery( $children.get( insertAtIndex ) ).offset().left; jQuery( $children.get( insertAtIndex ) ).before( placeholder ); const amountToOffsetLeftBy = 0 === insertAtIndex ? 4 : 8; // Offset by 8 in between rows, but only 4 for the first item in a group. left -= amountToOffsetLeftBy; // Offset the placeholder slightly so it appears between two fields. } left -= $row.offset().left; placeholder.style.left = left + 'px'; } function syncAfterDragAndDrop() { fixUnwrappedListItems(); toggleSectionHolder(); maybeFixEndDividers(); maybeDeleteEmptyFieldGroups(); updateFieldOrder(); const event = new Event( 'frm_sync_after_drag_and_drop', { bubbles: false }); document.dispatchEvent( event ); } function maybeFixEndDividers() { document.querySelectorAll( '.edit_field_type_end_divider' ).forEach( endDivider => endDivider.parentNode.appendChild( endDivider ) ); } function maybeDeleteEmptyFieldGroups() { document.querySelectorAll( 'li.form_field_box:not(.form-field)' ).forEach( fieldGroup => ! fieldGroup.children.length && fieldGroup.remove() ); } function fixUnwrappedListItems() { const lists = document.querySelectorAll( 'ul#frm-show-fields, ul.start_divider' ); lists.forEach( list => { list.childNodes.forEach( child => { if ( 'undefined' === typeof child.classList ) { return; } if ( child.classList.contains( 'edit_field_type_end_divider' ) ) { // Never wrap end divider in place. return; } if ( 'undefined' !== typeof child.classList && child.classList.contains( 'form-field' ) ) { wrapFieldLiInPlace( child ); } } ); } ); } function deleteEmptyDividerWrappers() { const dividers = document.querySelectorAll( 'ul.start_divider' ); if ( ! dividers.length ) { return; } dividers.forEach( function( divider ) { const 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(); } } ); } ); } function getFieldsInRow( $row ) { let $fields = jQuery(); const row = $row.get( 0 ); if ( ! row.children ) { return $fields; } Array.from( row.children ).forEach( child => { if ( 'none' === child.style.display ) { return; } const classes = child.classList; if ( ! classes.contains( 'form-field' ) || classes.contains( 'edit_field_type_end_divider' ) || classes.contains( 'frm-sortable-helper' ) ) { return; } $fields = $fields.add( child ); } ); return $fields; } 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( 'div' ); ul.classList.add( 'frm-dropdown-menu', 'dropdown-menu', 'dropdown-menu-right' ); 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 * @param {Object} previousSection * @returns {void} */ function updateFieldAfterMovingBetweenSections( currentItem, previousSection ) { if ( ! currentItem.hasClass( 'form-field' ) ) { // currentItem is a field group. Call for children recursively. getFieldsInRow( jQuery( currentItem.get( 0 ).firstChild ) ).each( function() { updateFieldAfterMovingBetweenSections( jQuery( this ), previousSection ); } ); return; } const fieldId = currentItem.attr( 'id' ).replace( 'frm_field_id_', '' ); const section = getSectionForFieldPlacement( currentItem ); const formId = getFormIdForFieldPlacement( section ); const sectionId = getSectionIdForFieldPlacement( section ); const previousFormId = previousSection ? getFormIdForFieldPlacement( jQuery( previousSection.parentNode ) ) : 0; jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_update_field_after_move', form_id: formId, field: fieldId, section_id: sectionId, previous_form_id: previousFormId, 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 {string} fieldType */ function insertNewFieldByDragging( fieldType ) { const placeholder = document.getElementById( 'frm_drag_placeholder' ); const loadingID = fieldType.replace( '|', '-' ) + '_' + getAutoId(); const loading = tag( 'li', { id: loadingID, className: 'frm-wait frmbutton_loadingnow' } ); const $placeholder = jQuery( loading ); const currentItem = jQuery( placeholder ); const section = getSectionForFieldPlacement( currentItem ); const formId = getFormIdForFieldPlacement( section ); const sectionId = getSectionIdForFieldPlacement( section ); placeholder.parentNode.insertBefore( loading, placeholder ); placeholder.remove(); syncLayoutClasses( $placeholder ); let 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 ) { let replaceWith; document.getElementById( 'frm_form_editor_container' ).classList.add( 'frm-has-fields' ); const $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 = msgAsjQueryObject( msg ); if ( ! $placeholder.get( 0 ).parentNode.parentNode.classList.contains( 'ui-draggable' ) ) { // If a field group wasn't draggable because it only had a single field, make it draggable. makeDraggable( $placeholder.get( 0 ).parentNode.parentNode, '.frm-move' ); } } $placeholder.replaceWith( replaceWith ); updateFieldOrder(); afterAddField( msg, false ); if ( $siblings.length ) { syncLayoutClasses( $siblings.first() ); } toggleSectionHolder(); if ( ! $siblings.length ) { makeDroppable( replaceWith.get( 0 ).querySelector( 'ul.frm_sorting' ) ); makeDraggable( replaceWith.get( 0 ).querySelector( 'li.form-field' ), '.frm-move' ); } else { makeDraggable( replaceWith.get( 0 ), '.frm-move' ); } }, error: handleInsertFieldError }); } function moveFieldThatAlreadyExists( draggable, placeholder ) { placeholder.parentNode.insertBefore( draggable, placeholder ); } function msgAsjQueryObject( msg ) { const element = div(); element.innerHTML = msg; return jQuery( element.firstChild ); } function handleInsertFieldError( jqXHR, _, errorThrown ) { maybeShowInsertFieldError( errorThrown, jqXHR ); } function maybeShowInsertFieldError( errorThrown, jqXHR ) { if ( ! jqXHRAborted( jqXHR ) ) { infoModal( errorThrown + '. Please try again.' ); } } function jqXHRAborted( jqXHR ) { return jqXHR.status === 0 || jqXHR.readyState === 0; } /** * 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( draggable, droppable ) { if ( false === droppable ) { // Don't show drop placeholder if dragging somewhere off of the droppable area. return false; } if ( droppable.closest( '.frm-sortable-helper' ) ) { // Do not allow drop into draggable. return false; } if ( 'frm-show-fields' === droppable.id ) { // Everything can be dropped into the main list of fields. return true; } if ( ! droppable.classList.contains( 'start_divider' ) ) { const $fieldsInRow = getFieldsInRow( jQuery( droppable ) ); if ( ! groupCanFitAnotherField( $fieldsInRow, jQuery( draggable ) ) ) { // Field group is full and cannot accept another field. return false; } } const isNewField = draggable.classList.contains( 'frm-new-field' ); if ( isNewField ) { return allowNewFieldDrop( draggable, droppable ); } return allowMoveField( draggable, droppable ); } // Don't allow a new page break or hidden field in a field group. // Don't allow a new field into a field group that includes a page break or hidden field. // Don't allow a new section inside of a section. // Don't allow an embedded form in a section. function allowNewFieldDrop( draggable, droppable ) { const classes = draggable.classList; const newPageBreakField = classes.contains( 'frm_tbreak' ); const newHiddenField = classes.contains( 'frm_thidden' ); const newSectionField = classes.contains( 'frm_tdivider' ); const newEmbedField = classes.contains( 'frm_tform' ); const newFieldWillBeAddedToAGroup = ! ( 'frm-show-fields' === droppable.id || droppable.classList.contains( 'start_divider' ) ); if ( newFieldWillBeAddedToAGroup ) { if ( groupIncludesBreakOrHidden( droppable ) ) { // Never allow any field beside a page break or a hidden field. return false; } return ! newHiddenField && ! newPageBreakField; } const fieldTypeIsAlwaysAllowed = ! newPageBreakField && ! newHiddenField && ! newSectionField && ! newEmbedField; if ( fieldTypeIsAlwaysAllowed ) { return true; } const newFieldWillBeAddedToASection = droppable.classList.contains( 'start_divider' ) || null !== droppable.closest( '.start_divider' ); if ( newFieldWillBeAddedToASection ) { // Don't allow a section or an embedded form in a section. return ! newEmbedField && ! newSectionField; } return true; } function allowMoveField( draggable, droppable ) { if ( isFieldGroup( draggable ) ) { return allowMoveFieldGroup( draggable, droppable ); } const isPageBreak = draggable.classList.contains( 'edit_field_type_break' ); if ( isPageBreak ) { // Page breaks are only allowed in the main list of fields, not in sections or in field groups. return false; } if ( droppable.classList.contains( 'start_divider' ) ) { return allowMoveFieldToSection( draggable ); } const isHiddenField = draggable.classList.contains( 'edit_field_type_hidden' ); if ( isHiddenField ) { // Hidden fields should not be added to field groups since they're not shown and don't make sense with the grid distribution. return false; } return allowMoveFieldToGroup( draggable, droppable ); } function isFieldGroup( draggable ) { return draggable.classList.contains( 'frm_field_box' ) && ! draggable.classList.contains( 'form-field' ); } function allowMoveFieldGroup( fieldGroup, droppable ) { if ( droppable.classList.contains( 'start_divider' ) && null === fieldGroup.querySelector( '.start_divider' ) ) { // Allow a field group with no section inside of a section. return true; } return false; } function allowMoveFieldToSection( draggable ) { const draggableIncludeEmbedForm = draggable.classList.contains( 'edit_field_type_form' ) || draggable.querySelector( '.edit_field_type_form' ); if ( draggableIncludeEmbedForm ) { // Do not allow an embedded form inside of a section. return false; } const draggableIncludesSection = draggable.classList.contains( 'edit_field_type_divider' ) || draggable.querySelector( '.edit_field_type_divider' ); if ( draggableIncludesSection ) { // Do not allow a section inside of a section. return false; } return true; } function allowMoveFieldToGroup( draggable, group ) { if ( groupIncludesBreakOrHidden( group ) ) { // Never allow any field beside a page break or a hidden field. return false; } const isFieldGroup = jQuery( draggable ).children( 'ul.frm_sorting' ).not( '.start_divider' ).length > 0; if ( isFieldGroup ) { // Do not allow a field group directly inside of a field group unless it's in a section. return false; } const draggableIncludesASection = draggable.classList.contains( 'edit_field_type_divider' ) || draggable.querySelector( '.edit_field_type_divider' ); const draggableIsEmbedField = draggable.classList.contains( 'edit_field_type_form' ); const groupIsInASection = null !== group.closest( '.start_divider' ); if ( groupIsInASection && ( draggableIncludesASection || draggableIsEmbedField ) ) { // Do not allow a section or an embed field inside of a section. return false; } return true; } function groupIncludesBreakOrHidden( group ) { return null !== group.querySelector( '.edit_field_type_break, .edit_field_type_hidden' ); } 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 ) { const thisField = document.getElementById( fieldId ); const $thisField = jQuery( thisField ); const field = []; const addHtmlToField = element => { const frmHiddenFdata = element.querySelector( '.frm_hidden_fdata' ); element.classList.add( 'frm_load_now' ); if ( frmHiddenFdata !== null ) { field.push( frmHiddenFdata.innerHTML ); } }; let 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: html => handleAjaxLoadFieldSuccess( html, $thisField, field ) }); } function handleAjaxLoadFieldSuccess( html, $thisField, field ) { let 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' ); makeDraggable( document.getElementById( 'frm_field_id_' + key ) ); } $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(); const loadedEvent = new Event( 'frm_ajax_loaded_field', { bubbles: false }); loadedEvent.frmFields = field.map( f => JSON.parse( f ) ); document.dispatchEvent( loadedEvent ); } function addFieldClick() { /*jshint validthis:true */ const $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; } const $button = $thisObj.closest( '.frmbutton' ); const fieldType = $button.attr( 'id' ); let hasBreak = 0; if ( 'summary' === fieldType ) { hasBreak = $newFields.children( 'li[data-type="break"]' ).length > 0 ? 1 : 0; } const 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' ); const replaceWith = wrapFieldLi( msg ); $newFields.append( replaceWith ); afterAddField( msg, true ); replaceWith.each( function() { makeDroppable( this.querySelector( 'ul.frm_sorting' ) ); makeDraggable( this.querySelector( '.form-field' ), '.frm-move' ); } ); }, error: handleInsertFieldError }); return false; } 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; let replaceWith; if ( null !== newRowId ) { newRow = document.getElementById( newRowId ); if ( null !== newRow ) { replaceWith = msgAsjQueryObject( msg ); jQuery( newRow ).append( replaceWith ); makeDraggable( replaceWith.get( 0 ), '.frm-move' ); 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 ) { replaceWith = msgAsjQueryObject( msg ); $field.after( replaceWith ); syncLayoutClasses( $field ); makeDraggable( replaceWith.get( 0 ), '.frm-move' ); } else { replaceWith = wrapFieldLi( msg ); $field.parent().parent().after( replaceWith ); makeDroppable( replaceWith.get( 0 ).querySelector( 'ul.frm_sorting' ) ); makeDraggable( replaceWith.get( 0 ).querySelector( 'li.form-field' ), '.frm-move' ); } updateFieldOrder(); afterAddField( msg, false ); maybeDuplicateUnsavedSettings( fieldId, msg ); toggleOneSectionHolder( replaceWith.find( '.start_divider' ) ); } }); 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 = postBodyContent; 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.show .frm-dropdown-menu' ); 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( 'div' ); li.classList.add( 'frm_more_options_li', 'dropdown-item' ); 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( field ) { const wrapper = div(); if ( 'string' === typeof field ) { wrapper.innerHTML = field; } else { wrapper.appendChild( field ); } let result = jQuery(); Array.from( wrapper.children ).forEach( li => { result = result.add( jQuery( '
  • ' ) .addClass( 'frm_field_box' ) .html( jQuery( '
  • ' ); html = html.replaceAll( '
  • ', '
  • ', '' ); ul.outerHTML = html; } } ); function frm_remove_tag( htmlTag ) { // eslint-disable-line camelcase console.warn( 'DEPRECATED: function frm_remove_tag in v2.0' ); jQuery( htmlTag ).remove(); } function frm_show_div( div, value, showIf, classId ) { // eslint-disable-line camelcase if ( value == showIf ) { jQuery( classId + div ).fadeIn( 'slow' ).css( 'visibility', 'visible' ); } else { jQuery( classId + div ).fadeOut( 'slow' ); } } function frmCheckAll( checked, n ) { jQuery( 'input[name^="' + n + '"]' ).prop( 'checked', ! ! checked ); } function frmCheckAllLevel( checked, n, level ) { var $kids = jQuery( '.frm_catlevel_' + level ).children( '.frm_checkbox' ).children( 'label' ); $kids.children( 'input[name^="' + n + '"]' ).prop( 'checked', ! ! checked ); } function frm_add_logic_row( id, formId ) { // eslint-disable-line camelcase console.warn( 'DEPRECATED: function frm_add_logic_row in v2.0' ); jQuery.ajax({ type: 'POST', url: ajaxurl, data: { action: 'frm_add_logic_row', form_id: formId, field_id: id, meta_name: jQuery( '#frm_logic_row_' + id + ' > div' ).length, nonce: frmGlobal.nonce }, success: function( html ) { jQuery( '#frm_logic_row_' + id ).append( html ); } }); return false; } function frmGetFieldValues( fieldId, cur, rowNumber, fieldType, htmlName ) { if ( fieldId ) { jQuery.ajax({ type: 'POST', url: ajaxurl, data: 'action=frm_get_field_values¤t_field=' + cur + '&field_id=' + fieldId + '&name=' + htmlName + '&t=' + fieldType + '&form_action=' + jQuery( 'input[name="frm_action"]' ).val() + '&nonce=' + frmGlobal.nonce, success: function( msg ) { document.getElementById( 'frm_show_selected_values_' + cur + '_' + rowNumber ).innerHTML = msg; } }); } } function frmImportCsv( formID ) { var urlVars = ''; if ( typeof __FRMURLVARS !== 'undefined' ) { urlVars = __FRMURLVARS; } jQuery.ajax({ type: 'POST', url: ajaxurl, data: 'action=frm_import_csv&nonce=' + frmGlobal.nonce + '&frm_skip_cookie=1' + urlVars, success: function( count ) { var max = jQuery( '.frm_admin_progress_bar' ).attr( 'aria-valuemax' ); var imported = max - count; var percent = ( imported / max ) * 100; jQuery( '.frm_admin_progress_bar' ).css( 'width', percent + '%' ).attr( 'aria-valuenow', imported ); if ( parseInt( count, 10 ) > 0 ) { jQuery( '.frm_csv_remaining' ).html( count ); frmImportCsv( formID ); } else { jQuery( document.getElementById( 'frm_import_message' ) ).html( frm_admin_js.import_complete ); setTimeout( function() { location.href = '?page=formidable-entries&frm_action=list&form=' + formID + '&import-message=1'; }, 2000 ); } } }); }