Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c707b68
Work on adding show options to code list pop up
Crabcyborg Nov 17, 2023
5d653ef
Fix merge conflict and merge master
AbdiTolesa Sep 20, 2024
e54e79e
Add show=label shortcode types to calculation fields popup
AbdiTolesa Sep 20, 2024
d0e5cc0
Fix eslint error
AbdiTolesa Sep 23, 2024
dc3afa1
Move name field additional shortcode variants implementation to pro b…
AbdiTolesa Sep 26, 2024
2d3c6b7
Undo last commit
AbdiTolesa Sep 26, 2024
9d04319
Refactor code a bit
AbdiTolesa Sep 26, 2024
e4b34b6
Add a return type definition
AbdiTolesa Sep 26, 2024
65de1c9
Reduce nesting complication
AbdiTolesa Sep 26, 2024
bbbbb97
Add condition check for showing show=xx shortcodes in calculation popup
AbdiTolesa Sep 26, 2024
d6b8a36
Add inline comment to clarify condition check
AbdiTolesa Sep 26, 2024
cdafa45
Add Rename function
AbdiTolesa Sep 26, 2024
8d1c7f5
Fix eslint error
AbdiTolesa Oct 1, 2024
f80ffde
Improve performance
AbdiTolesa Oct 3, 2024
b528490
Merge branch 'master' into work_on_adding_show_options_to_code_list_p…
Crabcyborg Jan 9, 2025
9152b45
Make sure a function always return boolean
AbdiTolesa Jan 12, 2025
3ca1927
Merge branch 'work_on_adding_show_options_to_code_list_popup' of http…
AbdiTolesa Jan 12, 2025
7da58a6
Merge branch 'master' into work_on_adding_show_options_to_code_list_p…
Crabcyborg Feb 14, 2025
5cbcf7a
Merge master
AbdiTolesa Oct 23, 2025
5319d99
Move changes to source file
AbdiTolesa Oct 23, 2025
ee49592
Build files
AbdiTolesa Oct 23, 2025
20367ef
Fix eslint errors
AbdiTolesa Oct 23, 2025
cb38709
Get rid of unnecessary checks dependent on Pro
AbdiTolesa Oct 27, 2025
54305f9
Add Address field part shortcodes to calculation popup
shervElmi Dec 8, 2025
84962d2
Refactor: Improve maybeAddAddressPartShortcodes with modern ES6 syntax
shervElmi Dec 8, 2025
1ad9068
Refactor: Clean up JSDoc parameter formatting in maybeAddAddressPartS…
shervElmi Dec 8, 2025
434318a
Add extensibility hook for field part shortcodes in calculation popup
shervElmi Dec 9, 2025
6b72e5c
Merge pull request #2639 from Strategy11/feature/address-field-show-o…
Crabcyborg Dec 9, 2025
fb5eeb3
Rebuild files
AbdiTolesa Dec 10, 2025
6c3eae1
Rebuild files
AbdiTolesa Dec 10, 2025
9f75a6c
Rebuild files
AbdiTolesa Dec 10, 2025
1bb6eb7
Rebuild files and merge master
AbdiTolesa Dec 10, 2025
56d366e
Field shortcode popup improvements
Crabcyborg Aug 6, 2026
89eacb4
Merge branch 'master' into work_on_adding_show_options_to_code_list_p…
Crabcyborg Aug 6, 2026
ec88b23
Run build
Crabcyborg Aug 6, 2026
be6808a
Exclude from math calc options
Crabcyborg Aug 6, 2026
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
87 changes: 87 additions & 0 deletions classes/controllers/FrmFormsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,93 @@ private static function advanced_helpers( $atts ) {
return apply_filters( 'frm_advanced_helpers', $advanced_helpers, $atts );
}

/**
* Adds a shortcode for each part of a multi-part field to the field shortcode list,
* so a single part can be used on its own, like [25 show=first] for a Name field.
*
* @since x.x
*
* @param array $atts Includes 'field'.
*
* @return void
*/
public static function field_part_shortcodes( $atts ) {
$field = $atts['field'];

foreach ( self::get_field_parts( $field ) as $part => $label ) {
FrmFormsHelper::insert_opt_html(
array(
'id' => $field->id . ' show=' . $part,
'key' => $field->field_key . ' show=' . $part,
// Truncate the key on its own so the part stays readable.
'key_label' => FrmAppHelper::truncate( $field->field_key, 7 ) . ' show=' . $part,
'name' => $field->name . ' (' . $label . ')',
'type' => $field->type,
'class' => 'frm-customize-list dropdown-item',
)
);
unset( $part, $label );
}
}

/**
* Gets the parts of a multi-part field that can be shown on their own with a show= shortcode option.
*
* @since x.x
*
* @param stdClass $field
*
* @return array Part labels keyed by the show= option value.
*/
private static function get_field_parts( $field ) {
$parts = 'name' === $field->type ? self::get_name_field_parts( $field ) : array();

/**
* Allows add-ons to add the parts of their own multi-part fields, like the Pro Address field.
*
* @since x.x
*
* @param array $parts Part labels keyed by the show= option value.
* @param stdClass $field The field the parts belong to.
*/
return apply_filters( 'frm_field_parts_for_shortcodes', $parts, $field );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

}

/**
* Gets the parts of a Name field that are in use. Only the parts included in the
* selected name layout hold a value, so the rest would always show as blank.
*
* @since x.x
*
* @param stdClass $field
*
* @return array Part labels keyed by the show= option value, in layout order.
*/
private static function get_name_field_parts( $field ) {
$labels = array(
'first' => __( 'First', 'formidable' ),
'middle' => __( 'Middle', 'formidable' ),
'last' => __( 'Last', 'formidable' ),
);
$layout = FrmField::get_option( $field, 'name_layout' );

if ( ! $layout ) {
$layout = 'first_last';
}

// The layout option names the parts in use, in display order, like first_middle_last.
$parts = array();

foreach ( explode( '_', $layout ) as $part ) {
if ( isset( $labels[ $part ] ) ) {
$parts[ $part ] = $labels[ $part ];
}
unset( $part );
}

return $parts;
}

/**
* Get an array of the options to display in the advanced tab
* of the customization panel
Expand Down
1 change: 1 addition & 0 deletions classes/controllers/FrmHooksController.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ public static function load_admin_hooks() {
add_action( 'admin_menu', 'FrmFormsController::menu', 10 );
add_action( 'admin_head-toplevel_page_formidable', 'FrmFormsController::head' );
add_action( 'frm_after_field_options', 'FrmFormsController::logic_tip' );
add_action( 'frm_field_code_tab', 'FrmFormsController::field_part_shortcodes' );
add_filter( 'frm_fields_in_form_builder', 'FrmFormsController::update_form_builder_fields' );

add_filter( 'set-screen-option', 'FrmFormsController::save_per_page', 10, 3 );
Expand Down
2 changes: 1 addition & 1 deletion classes/helpers/FrmFormsHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ public static function insert_opt_html( $args ) {

echo esc_html( $truncated_name );
?>
<span>[<?php echo esc_html( FrmAppHelper::truncate( $args['key_label'] ?? $args['key'], 7 ) ); ?>]</span>
<span>[<?php echo esc_html( $args['key_label'] ?? FrmAppHelper::truncate( $args['key'], 7 ) ); ?>]</span>
</a>
</li>
<?php
Expand Down
3 changes: 1 addition & 2 deletions css/frm_admin.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion css/frm_testing_mode.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion js/formidable_admin.js

Large diffs are not rendered by default.

155 changes: 143 additions & 12 deletions js/src/admin/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3317,19 +3317,150 @@ window.frmAdminBuildJS = function() {
continue;
}

const anchor = document.createElement( 'a' );
anchor.setAttribute( 'href', '#' );
anchor.setAttribute( 'data-code', fields[ i ].fieldId );
anchor.classList.add( 'frm_insert_code' );
anchor.append( span( fields[ i ].fieldName ) );
anchor.append( span( { className: 'frm-text-sm frm-text-grey-500', text: `[${ fields[ i ].fieldId }]` } ) );

const li = document.createElement( 'li' );
li.classList.add( `frm-field-list-${ fieldId }` );
li.classList.add( `frm-field-list-${ fields[ i ].fieldType }` );
li.append( anchor );
list.append( li );
addCalcFieldLiToList( list, fieldId, fields[ i ].fieldId, fields[ i ].fieldName, fields[ i ].fieldType );

if ( ! isSummary ) {
// The summary field list is a list of fields to exclude, not a list of shortcodes, so field parts don't belong in it.
addFieldPartShortcodes( fields[ i ], fieldId, list );
}
}
}

/**
* Adds shortcodes for the individual parts of a multi-part field, like [25 show=last] for a Name field.
*
* @since x.x
*
* @param {Object} field Field object containing fieldType, fieldId, and fieldName.
* @param {string} fieldId ID of the field the popup was opened for.
* @param {HTMLElement} list The 'ul' element that contains field shortcodes available for calculation.
*
* @return {void}
*/
function addFieldPartShortcodes( field, fieldId, list ) {
if ( ! isTextCalc( fieldId ) ) {
// Only a text calculation resolves a show= option. In any other type the shortcode
// is left as-is and the formula fails to evaluate, so don't offer the parts at all.
return;
}

maybeAddNamePartShortcodes( field, fieldId, list );

/**
* Allows add-ons to add field part shortcodes to calculation popup.
*
* @since x.x
*
* @param {Object} hookArgs Arguments passed to the hook.
* @param {Object} hookArgs.field Field object containing fieldType, fieldId, and fieldName.
* @param {string} hookArgs.fieldId ID of the field triggering the popup.
* @param {HTMLElement} hookArgs.list The 'ul' element containing field shortcodes.
* @param {Function} hookArgs.addCalcFieldLiToList Helper function: addCalcFieldLiToList(list, fieldId, code, label, fieldType).
*/
wp.hooks.doAction( 'frm_add_calc_field_shortcodes', { field, fieldId, list, addCalcFieldLiToList } );
}

/**
* Checks whether the calculation being edited is a text calculation.
*
* @since x.x
*
* @param {string} fieldId ID of the field the calculation belongs to.
*
* @return {boolean} True when the calculation type is text.
*/
function isTextCalc( fieldId ) {
const calcType = document.querySelector( `input[name="field_options[calc_type_${ fieldId }]"]:checked` );
return calcType ? 'text' === calcType.value : false;
}

/**
* Adds shortcodes like [nameFieldId show=last] to the calculation popup.
*
* @since x.x
*
* @param {Object} field Field object containing fieldType, fieldId, and fieldName.
* @param {string} fieldId ID of the field the popup was opened for.
* @param {HTMLElement} list The 'ul' element that contains field shortcodes available for calculation.
*
* @return {void}
*/
function maybeAddNamePartShortcodes( field, fieldId, list ) {
if ( 'name' !== field.fieldType ) {
return;
}

Object.entries( getNamePartLabels( field.fieldId ) ).forEach(
( [ code, label ] ) => {
addCalcFieldLiToList(
list,
fieldId,
`${ field.fieldId } show=${ code }`,
`${ field.fieldName } (${ label })`,
field.fieldType
);
}
);
}

/**
* Gets the parts of a Name field that are in use, keyed by their show= value.
* Only the parts included in the selected name layout have a value to show.
*
* @since x.x
*
* @param {string} nameFieldId ID of the Name field.
*
* @return {Object} Part labels keyed by their show= value, in layout order.
*/
function getNamePartLabels( nameFieldId ) {
const labels = {
first: __( 'First', 'formidable' ),
middle: __( 'Middle', 'formidable' ),
last: __( 'Last', 'formidable' )
};
// The layout option names the parts in use, in display order, like first_middle_last.
const layout = document.getElementById( `name_layout_${ nameFieldId }` )?.value || 'first_last';
const parts = {};

layout.split( '_' ).forEach( part => {
if ( labels[ part ] ) {
parts[ part ] = labels[ part ];
}
} );

return parts;
}

Comment thread
Crabcyborg marked this conversation as resolved.
/**
* Adds a row to a calculation box's field shortcode list.
*
* @since x.x
*
* @param {HTMLElement} list The 'ul' element that contains field shortcodes available for calculation.
* @param {string} fieldId ID of the field the popup was opened for.
* @param {string} code The shortcode to insert, without the brackets.
* @param {string} label The name shown for the row.
* @param {string} fieldType Type of the field the shortcode belongs to.
*
* @return {void}
*/
function addCalcFieldLiToList( list, fieldId, code, label, fieldType ) {
const anchor = a( {
className: 'frm_insert_code',
children: [
span( label ),
span( { className: 'frm-text-sm frm-text-grey-500', text: `[${ code }]` } )
],
data: { code }
} );

list.append(
tag( 'li', {
className: `frm-field-list-${ fieldId } frm-field-list-${ fieldType }`,
child: anchor
} )
);
}

/**
Expand Down
Loading