Skip to content
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cddce18
Make conditional logic dropdown in sync with options
AbdiTolesa Apr 1, 2024
ea6ace9
Fix issue of creating double options in conditional logic dropdown
AbdiTolesa Apr 1, 2024
f530062
Use const instead of var
AbdiTolesa Apr 1, 2024
2e82f52
Add function comments
AbdiTolesa Apr 1, 2024
92d001a
Remove debug line and directly return function result
AbdiTolesa Apr 3, 2024
9b713d1
Fix eslint error
AbdiTolesa Apr 3, 2024
d50381a
Use choice value for querying value dropdown options
AbdiTolesa Apr 3, 2024
9d9c4fc
Delete conditional logic opts when field option is deleted
AbdiTolesa Apr 3, 2024
a7a9de1
Add semicolon
AbdiTolesa Apr 3, 2024
a0fa50b
Fix potential error
AbdiTolesa Apr 3, 2024
ad3db15
Fix potential bug
AbdiTolesa Apr 3, 2024
936eecb
Add a check if separate values is checked
AbdiTolesa Apr 3, 2024
77203f3
Edge cases considered
AbdiTolesa Apr 3, 2024
2ca37f9
Prepend new options to conditional logic value dropdown
AbdiTolesa Apr 4, 2024
2503aff
Improve codestyles
AbdiTolesa Apr 4, 2024
d2aab91
Add a little refactoring
AbdiTolesa Apr 4, 2024
804b86e
Avoid potential bug
AbdiTolesa Apr 4, 2024
594942f
Add missing function comment
AbdiTolesa Apr 4, 2024
2678199
Undo change not needed
AbdiTolesa Apr 4, 2024
d5d1d66
Improve DOM query
AbdiTolesa Apr 4, 2024
7baad48
Remove commented lines and use Array.forEach
AbdiTolesa Apr 5, 2024
96bef34
Move function that deletes conditional logic opts to pro using hook
AbdiTolesa Apr 9, 2024
4be50c8
Fix merge conflict
AbdiTolesa Aug 7, 2024
ceddb1f
Fix merge conflict with #1894
AbdiTolesa Aug 7, 2024
7e7bd53
Fix eslint errors
AbdiTolesa Aug 7, 2024
6971564
Merge branch 'master' into issue-2911-fix_conditional_logic_option
Crabcyborg Aug 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 129 additions & 13 deletions js/formidable_admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3590,6 +3590,7 @@ function frmAdminBuildJS() {
fieldId = this.getAttribute( 'data-fid' );

jQuery( parentLi ).fadeOut( 'slow', function() {
wp.hooks.doAction( 'frm_before_delete_field_option', this );
jQuery( parentLi ).remove();

const hasOther = jQuery( parentUl ).find( '.frm_other_option' );
Expand Down Expand Up @@ -4971,10 +4972,69 @@ function frmAdminBuildJS() {
}
}

/**
* Returns an object that has the old and new values and labels, when a field choice is changed.
*
* @param {HTMLElement} input
* @returns {Object}
*/
function getChoiceOldAndNewValues( input ) {
const { oldValue, oldLabel } = getChoiceOldValueAndLabel( input );
const { newValue, newLabel } = getChoiceNewValueAndLabel( input );

return { oldValue, oldLabel, newValue, newLabel };
}

/**
* Returns an object that has the new value and label, when a field choice is changed.
*
* @param {HTMLElement} choiceElement
* @returns {Object}
*/
function getChoiceNewValueAndLabel( choiceElement ) {
const singleOptionContainer = choiceElement.closest( '.frm_single_option' );

let newValue, newLabel;

if ( choiceElement.parentElement.classList.contains( 'frm_single_option' ) ) { // label changed
newValue = singleOptionContainer.querySelector( '.frm_option_key input[type="text"]' ).value;
newLabel = choiceElement.value;
return { newValue, newLabel };
}

// saved value changed
newLabel = singleOptionContainer.querySelector( 'input[type="text"]' ).value;
newValue = choiceElement.value;
return { newValue, newLabel };
}

/**
* Returns an object that has the old value and label, when a field choice is changed.
*
* @param {HTMLElement} choiceElement
* @returns {Object}
*/
function getChoiceOldValueAndLabel( choiceElement ) {
const usingSeparateValues = choiceElement.closest( '.frm-single-settings' ).querySelector( '.frm_toggle_sep_values' ).checked;
const singleOptionContainer = choiceElement.closest( '.frm_single_option' );

let oldValue, oldLabel;

if ( usingSeparateValues ) {
if ( choiceElement.parentElement.classList.contains( 'frm_single_option' ) ) { // label changed
oldValue = singleOptionContainer.querySelector( '.frm_option_key input[type="text"]' ).getAttribute( 'data-value-on-focus' );
oldLabel = choiceElement.getAttribute( 'data-value-on-focus' );
return { oldValue, oldLabel };
}
}
oldValue = choiceElement.getAttribute( 'data-value-on-focus' );
oldLabel = singleOptionContainer.querySelector( 'input[type="text"]' ).getAttribute( 'data-value-on-focus' );

return { oldValue, oldLabel };
}

function onOptionTextBlur() {
let originalValue,
oldValue = this.getAttribute( 'data-value-on-focus' ),
newValue = this.value,
fieldId,
fieldIndex,
logicId,
Expand All @@ -4989,11 +5049,15 @@ function frmAdminBuildJS() {
optionMatches,
option;

if ( oldValue === newValue ) {
const { oldValue, oldLabel, newValue, newLabel } = getChoiceOldAndNewValues( this );

if ( oldValue === newValue && oldLabel === newLabel ) {
return;
}

fieldId = jQuery( this ).closest( '.frm-single-settings' ).attr( 'data-fid' );
const singleSettingsContainer = this.closest( '.frm-single-settings' );

fieldId = singleSettingsContainer.getAttribute( 'data-fid' );
originalValue = this.getAttribute( 'data-value-on-load' );

// check if the newValue is already mapped to another option
Expand Down Expand Up @@ -5037,8 +5101,14 @@ function frmAdminBuildJS() {
optionMatches = valueSelect.querySelectorAll( 'option[value="' + newValue + '"]' );

if ( ! optionMatches.length ) {
option = document.createElement( 'option' );
valueSelect.appendChild( option );
if ( ! singleSettingsContainer.querySelector( '.frm_toggle_sep_values' ).checked ) {
option = searchSelectByText( valueSelect, oldValue ); // Find conditional logic option with oldValue
}

if ( ! option ) {
option = document.createElement( 'option' );
valueSelect.appendChild( option );
}
}
}

Expand All @@ -5047,7 +5117,7 @@ function frmAdminBuildJS() {
}

option.setAttribute( 'value', newValue );
option.textContent = newValue;
option.textContent = newLabel;
Comment thread
Crabcyborg marked this conversation as resolved.

if ( fieldIds.indexOf( logicId ) === -1 ) {
fieldIds.push( logicId );
Expand All @@ -5061,6 +5131,26 @@ function frmAdminBuildJS() {
}
}

/**
* Returns an option element that matches a string with its text content.
*
* @param {HTMLElement} selectElement
* @param {string} searchText
* @returns {HTMLElement|null}
*/
function searchSelectByText( selectElement, searchText ) {
const options = selectElement.options;

for ( let i = 0; i < options.length; i++ ) {
const option = options[i];
if ( searchText === option.textContent ) {
return option;
}
}

return null;
}

function updateGetValueFieldSelection() {
/*jshint validthis:true */
const fieldID = this.id.replace( 'get_values_form_', '' );
Expand Down Expand Up @@ -5608,6 +5698,25 @@ function frmAdminBuildJS() {
adjustConditionalLogicOptionOrders( fieldId );
}

/**
* Returns an object that has a value and label for new conditional logic option, for a given option value.
*
* @param {Number} fieldId
* @param {string} expectedOption
* @returns {Object}
*/
function getNewConditionalLogicOption( fieldId, expectedOption ) {
const optionsContainer = document.getElementById( 'frm_field_' + fieldId + '_opts' );

const expectedOptionInput = optionsContainer.querySelector( 'input[value="' + expectedOption + '"]' );

if ( expectedOptionInput ) {
return getChoiceNewValueAndLabel( expectedOptionInput );
}

return { newValue: expectedOption, newLabel: expectedOption };
}
Comment thread
Crabcyborg marked this conversation as resolved.

function adjustConditionalLogicOptionOrders( fieldId, type ) {
let row, opts, logicId, valueSelect, optionLength, optionIndex, expectedOption, optionMatch, fieldOptions,
rows = builderPage.querySelectorAll( '.frm_logic_row' ),
Expand All @@ -5629,7 +5738,14 @@ function frmAdminBuildJS() {

for ( optionIndex = optionLength - 1; optionIndex >= 0; optionIndex-- ) {
expectedOption = fieldOptions[ optionIndex ];
optionMatch = valueSelect.querySelector( 'option[value="' + expectedOption + '"]' );
let expectedOptionValue = document.getElementById( 'frm_field_' + fieldId + '_opts' ).querySelector( '.frm_option_key input[type="text"]' )?.value;
if ( ! expectedOptionValue ) {
expectedOptionValue = expectedOption;
}

optionMatch = valueSelect.querySelector( 'option[value="' + expectedOptionValue + '"]' );

const { newValue, newLabel } = getNewConditionalLogicOption( fieldId, expectedOption );

const fieldChoices = document.querySelectorAll( '#frm_field_' + fieldId + '_opts input[data-value-on-focus]' );
const expectedChoiceEl = Array.from( fieldChoices ).find( element => element.value === expectedOption );
Expand All @@ -5640,7 +5756,7 @@ function frmAdminBuildJS() {
continue;
}
}
prependValueSelectWithOptionMatch( valueSelect, optionMatch, expectedOption );
prependValueSelectWithOptionMatch( valueSelect, optionMatch, newValue, newLabel );
}

optionMatch = valueSelect.querySelector( 'option[value=""]' );
Expand All @@ -5650,10 +5766,10 @@ function frmAdminBuildJS() {
}
}

function prependValueSelectWithOptionMatch( valueSelect, optionMatch, expectedOption ) {
if ( optionMatch === null ) {
optionMatch = frmDom.tag( 'option', { text: expectedOption });
optionMatch.value = expectedOption;
function prependValueSelectWithOptionMatch( valueSelect, optionMatch, newValue, newLabel ) {
if ( optionMatch === null && ! valueSelect.querySelector( 'option[value="' + newValue + '"]' )) {
optionMatch = frmDom.tag( 'option', { text: newLabel });
optionMatch.value = newValue;
}

valueSelect.prepend( optionMatch );
Expand Down