PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | js/admin/style.js +282 -82 6.25 → trunk View file →
@@ -2,9 +2,8 @@
2 2 * This script file handles style settings in the Lite plugin.
3 3 * Pro-specific features are in the style-settings.js file in Pro.
4 4 */
5 5 ( function() {
6 - /* globals frmDom, frmAdminBuild */
7 6 'use strict';
8 7
9 8 if ( ! document.getElementById( 'frm_active_style_form' ) ) {
10 9 return;
@@ -61,11 +60,100 @@
61 60 document.body.classList.remove( 'wp-core-ui' );
62 61 document.getElementById( 'frm_style_sidebar' ).classList.add( 'wp-core-ui' );
63 62
64 63 jQuery( document ).on( 'input change', 'input[data-frmrange]', initSliderPreview );
64 +
65 + initOptionLayoutPreview();
65 66 }
66 67
67 68 /**
69 + * Sync the radio/checkbox option layout (alignment) style settings to the preview form in real time.
70 + *
71 + * The layout is applied to the front end through a container class, so changing the style setting
72 + * does not re-render the preview form. This swaps the container class on preview fields that use the
73 + * style setting. The styler preview marks those fields with .frm-default-option-align, so fields with
74 + * their own alignment override are left untouched.
75 + *
76 + * @return {void}
77 + */
78 + function initOptionLayoutPreview() {
79 + bindOptionLayoutSelect( document.getElementById( 'frm_radio_align' ), '.frm_radio' );
80 + bindOptionLayoutSelect( document.getElementById( 'frm_check_align' ), '.frm_checkbox' );
81 + }
82 +
83 + /**
84 + * Listen for changes on an option layout style setting and update the preview to match.
85 + *
86 + * @param {HTMLSelectElement|null} select The style setting dropdown.
87 + * @param {string} optionSelector The single option selector ('.frm_radio' or '.frm_checkbox').
88 + * @return {void}
89 + */
90 + function bindOptionLayoutSelect( select, optionSelector ) {
91 + if ( ! select ) {
92 + return;
93 + }
94 +
95 + select.addEventListener( 'change', () => {
96 + updatePreviewOptionLayout( optionSelector, select.value );
97 + } );
98 + }
99 +
100 + /**
101 + * Replace the alignment container class on preview fields that are using the style setting.
102 + *
103 + * @param {string} optionSelector The single option selector ('.frm_radio' or '.frm_checkbox').
104 + * @param {string} newAlign The newly selected style alignment value.
105 + * @return {void}
106 + */
107 + function updatePreviewOptionLayout( optionSelector, newAlign ) {
108 + const newClass = optionLayoutAlignToClass( newAlign );
109 +
110 + if ( ! newClass ) {
111 + return;
112 + }
113 +
114 + const activeForm = document.getElementById( 'frm_active_style_form' );
115 + if ( ! activeForm ) {
116 + return;
117 + }
118 +
119 + const alignClasses = [ 'vertical_radio', 'horizontal_radio', 'frm_two_col', 'frm_three_col', 'frm_four_col' ];
120 + const containers = new Set();
121 +
122 + activeForm.querySelectorAll( optionSelector ).forEach( option => {
123 + const container = option.closest( '.frm_form_field' );
124 +
125 + // Only fields using the style setting (no override) are marked in the styler preview.
126 + if ( container?.classList.contains( 'frm-default-option-align' ) ) {
127 + containers.add( container );
128 + }
129 + } );
130 +
131 + containers.forEach( container => {
132 + container.classList.remove( ...alignClasses );
133 + container.classList.add( newClass );
134 + } );
135 + }
136 +
137 + /**
138 + * Map an option layout style value to its front-end container class.
139 + *
140 + * @param {string} align The style alignment value.
141 + * @return {string} The matching container class.
142 + */
143 + function optionLayoutAlignToClass( align ) {
144 + if ( 'inline' === align ) {
145 + return 'horizontal_radio';
146 + }
147 +
148 + if ( 'block' === align ) {
149 + return 'vertical_radio';
150 + }
151 +
152 + return align;
153 + }
154 +
155 + /**
68 156 * Initialize the slider functionality in the style preview.
69 157 *
70 158 * @param {HTMLElement} event
71 159 * @return {void}
@@ -95,11 +183,10 @@
95 183 * @return {void}
96 184 */
97 185 function initListPage() {
98 186 document.addEventListener( 'click', handleClickEventsForListPage );
99 - // Add a timeout so Pro has a chance to add a filter first.
100 - // 0 does not always work in Google Chrome, so use 1.
101 - setTimeout( addHamburgerMenusToCards, 1 );
187 + // The dropdown options are added on the first open, so there is no longer a filter from Pro to wait for here.
188 + addHamburgerMenusToCards();
102 189 initDatepickerSample();
103 190
104 191 const enableToggle = document.getElementById( 'frm_enable_styling' );
105 192 const styleIdInput = getStyleIdInput();
@@ -160,9 +247,9 @@
160 247 }
161 248
162 249 /**
163 250 * @param {string} labelPosition
164 - * @return {void}
251 + * @return {void} Changes the label position in the preview.
165 252 */
166 253 function changeLabelPositionsInPreview( labelPosition ) {
167 254 const input = tag( 'input' );
168 255 input.value = labelPosition;
@@ -255,9 +342,9 @@
255 342 * @param {Event} event
256 343 * @return {void}
257 344 */
258 345 function handleCommonClickEvents( event ) {
259 - const target = event.target;
346 + const { target } = event;
260 347
261 348 if ( 'frm_toggle_sample_form' === target.id || target.closest( '#frm_toggle_sample_form' ) ) {
262 349 toggleSampleForm();
263 350 return;
@@ -270,9 +357,8 @@
270 357 }
271 358
272 359 if ( target.classList.contains( 'frm-edit-style' ) || null !== target.closest( '.frm-edit-style' ) || 'frm_edit_style' === target.id ) {
273 360 modifyStylerUrl( target );
274 - return; // eslint-disable-line
275 361 }
276 362 }
277 363
278 364 /**
@@ -282,9 +368,9 @@
282 368 * @return {void}
283 369 */
284 370 function switchAdvancedSettingsFormAction( target ) {
285 371 const form = document.querySelector( '#frm_styling_form' );
286 - if ( null === form ) {
372 + if ( ! form ) {
287 373 return;
288 374 }
289 375 if ( target.closest( 'a#frm_style_back_to_quick_settings' ) ) {
290 376 form.action = form.action.replace( '&section=advanced-settings', '' );
@@ -322,13 +408,12 @@
322 408 * @param {Event} event
323 409 * @return {void}
324 410 */
325 411 function handleClickEventsForListPage( event ) {
326 - const target = event.target;
412 + const { target } = event;
327 413
328 414 if ( target.classList.contains( 'frm-style-card' ) || target.closest( '.frm-style-card' ) ) {
329 415 handleStyleCardClick( event );
330 - return; // eslint-disable-line
331 416 }
332 417 }
333 418
334 419 /**
@@ -338,9 +423,9 @@
338 423 * @param {Event} event
339 424 * @return {void}
340 425 */
341 426 function handleStyleCardClick( event ) {
342 - const target = event.target;
427 + const { target } = event;
343 428
344 429 if ( target.closest( '.dropdown' ) ) {
345 430 // Ignore the hamburger menu inside of the card.
346 431 return;
@@ -373,13 +458,11 @@
373 458
374 459 sampleForm.classList.remove( activeCard.dataset.classname );
375 460 sampleForm.classList.add( card.dataset.classname );
376 461
377 - if ( ! cardIsLocked ) {
378 - // Don't update the form when a locked card is clicked.
379 - styleIdInput.value = card.dataset.styleId;
380 - trackListPageChange();
381 - }
462 + // cardIsLocked is always false here due to early return above.
463 + styleIdInput.value = card.dataset.styleId;
464 + trackListPageChange();
382 465
383 466 setTimeout( enableLabelTransitions, 1 );
384 467
385 468 // We want to toggle the edit button so you can only leave the page to edit the style if it's active (to avoid unsaved changes).
@@ -565,9 +648,9 @@
565 648 return;
566 649 }
567 650
568 651 const anchor = clickTarget.hasAttribute( 'href' ) ? clickTarget : clickTarget.querySelector( 'a[href]' );
569 - anchor.setAttribute( 'href', anchor.getAttribute( 'href' ) + '&sample=1' );
652 + anchor.setAttribute( 'href', `${ anchor.getAttribute( 'href' ) }&sample=1` );
570 653 }
571 654
572 655 /**
573 656 * Add menu dropdowns to style cards dynamically on load.
@@ -587,9 +670,9 @@
587 670 if ( ! shouldAddMenuToCard( card ) ) {
588 671 return;
589 672 }
590 673
591 - card.appendChild( getHamburgerMenu( card.dataset ) );
674 + card.append( getHamburgerMenu( card.dataset ) );
592 675 }
593 676
594 677 /**
595 678 * Avoid adding a menu to an upsell card or a template card.
@@ -632,14 +715,78 @@
632 715 const hamburgerMenu = a( {
633 716 className: 'frm-dropdown-toggle dropdown-toggle',
634 717 child: svg( { href: '#frm_thick_more_vert_icon' } )
635 718 } );
636 - hamburgerMenu.setAttribute( 'data-toggle', 'dropdown' );
637 - hamburgerMenu.setAttribute( 'data-container', 'body' );
719 + hamburgerMenu.setAttribute( 'data-bs-toggle', 'dropdown' );
720 + hamburgerMenu.setAttribute( 'data-bs-container', 'body' );
638 721 hamburgerMenu.setAttribute( 'role', 'button' );
639 722 hamburgerMenu.setAttribute( 'tabindex', 0 );
640 723
641 - const isTemplate = 'undefined' !== typeof data.templateKey;
724 + const isTemplate = data.templateKey !== undefined;
725 +
726 + const dropdownMenu = div( {
727 + // Use dropdown-menu-right to avoid an overlapping issue with the card to the right (where the # of forms would appear above the menu).
728 + className: 'frm-dropdown-menu frm-style-options-menu frm-p-1'
729 + } );
730 +
731 + const isRtl = document.body.classList.contains( 'rtl' );
732 + dropdownMenu.classList.add( `dropdown-menu-${ isRtl ? 'left' : 'right' }` );
733 +
734 + dropdownMenu.setAttribute( 'role', 'menu' );
735 +
736 + fillDropdownMenuOnFirstOpen( hamburgerMenu, dropdownMenu, data, isTemplate );
737 +
738 + return div( {
739 + className: 'dropdown frm_wrap', // The .frm_wrap class prevents a blue outline on the active dropdown trigger.
740 + children: [ hamburgerMenu, dropdownMenu ]
741 + } );
742 + }
743 +
744 + /**
745 + * Add the options to a style card dropdown the first time that dropdown is opened.
746 + *
747 + * The options are built through the frm_style_card_dropdown_options filter, and Pro registers its
748 + * callback while its own script file runs. Adding the options while the page loads raced that file,
749 + * so a request for it that was slow to come back left every card holding the Lite only options.
750 + * Waiting for the first open takes the script order out of it, since Pro has always registered the
751 + * filter by the time a card can be clicked.
752 + *
753 + * @since 6.35
754 + *
755 + * @param {HTMLElement} hamburgerMenu The dropdown trigger.
756 + * @param {HTMLElement} dropdownMenu The dropdown to add the options to.
757 + * @param {DOMStringMap} data The dataset of the style card, or an object with the style ID on the edit page.
758 + * @param {boolean} isTemplate Whether the card is for a style template.
759 + * @return {void}
760 + */
761 + function fillDropdownMenuOnFirstOpen( hamburgerMenu, dropdownMenu, data, isTemplate ) {
762 + const fillDropdownMenu = () => {
763 + if ( dropdownMenu.children.length ) {
764 + return;
765 + }
766 +
767 + const options = getDropdownMenuOptions( data, isTemplate );
768 + dropdownMenu.append( ...options.map( wrapDropdownItem ) );
769 + };
770 +
771 + // Bootstrap fires this on the trigger before it measures and positions the dropdown.
772 + hamburgerMenu.addEventListener( 'show.bs.dropdown', fillDropdownMenu );
773 +
774 + // Fall back to the click in case the dropdown is ever opened without Bootstrap. Listen in the
775 + // capture phase so the options are in place before Bootstrap's own delegated handler runs.
776 + hamburgerMenu.addEventListener( 'click', fillDropdownMenu, true );
777 + }
778 +
779 + /**
780 + * Get the options for a single style card dropdown.
781 + *
782 + * @since 6.35
783 + *
784 + * @param {DOMStringMap} data The dataset of the style card, or an object with the style ID on the edit page.
785 + * @param {boolean} isTemplate Whether the card is for a style template.
786 + * @return {Array} The dropdown options, each an object with an anchor and a type.
787 + */
788 + function getDropdownMenuOptions( data, isTemplate ) {
642 789 let dropdownMenuOptions = [];
643 790
644 791 if ( isListPage ) {
645 792 const applyOption = a( {
@@ -680,23 +827,9 @@
680 827 if ( isListPage && ! isTemplate ) {
681 828 maybeAddDuplicateUpsell( dropdownMenuOptions );
682 829 }
683 830
684 - const dropdownMenu = div( {
685 - // Use dropdown-menu-right to avoid an overlapping issue with the card to the right (where the # of forms would appear above the menu).
686 - className: 'frm-dropdown-menu frm-style-options-menu frm-p-1',
687 - children: dropdownMenuOptions.map( wrapDropdownItem )
688 - } );
689 -
690 - const isRtl = document.body.classList.contains( 'rtl' );
691 - dropdownMenu.classList.add( 'dropdown-menu-' + ( isRtl ? 'left' : 'right' ) );
692 -
693 - dropdownMenu.setAttribute( 'role', 'menu' );
694 -
695 - return div( {
696 - className: 'dropdown frm_wrap', // The .frm_wrap class prevents a blue outline on the active dropdown trigger.
697 - children: [ hamburgerMenu, dropdownMenu ]
698 - } );
831 + return dropdownMenuOptions;
699 832 }
700 833
701 834 /**
702 835 * @param {Array} dropdownMenuOptions
@@ -801,9 +934,9 @@
801 934 // Create a form so we can listen to Enter key presses that trigger a form submit event.
802 935 const form = tag(
803 936 'form',
804 937 {
805 - child: labelledTextInput( 'frm_' + context + '_style_name_input', __( 'Style name', 'formidable' ), 'style_name' )
938 + child: labelledTextInput( `frm_${ context }_style_name_input`, __( 'Style name', 'formidable' ), 'style_name' )
806 939 }
807 940 );
808 941 form.addEventListener(
809 942 'submit',
@@ -878,8 +1011,26 @@
878 1011 // The button gets disabled on an input event when the name is empty.
879 1012 return;
880 1013 }
881 1014
1015 + if ( ! styleId || '0' === String( styleId ) ) {
1016 + // A new or duplicated style has no ID yet, so there is nothing to rename on the server.
1017 + // Update the post_title input (which overrides $_GET['style_name'] on save) and the
1018 + // visible style name instead of calling the rename_style endpoint.
1019 + const postTitleInput = document.querySelector( 'input[name="frm_style_setting[post_title]"]' );
1020 + if ( postTitleInput ) {
1021 + postTitleInput.value = newStyleName;
1022 + }
1023 +
1024 + const styleNameElement = document.getElementById( 'frm_style_name' );
1025 + if ( styleNameElement ) {
1026 + styleNameElement.textContent = newStyleName;
1027 + }
1028 +
1029 + success( __( 'Style has been renamed successfully', 'formidable' ) );
1030 + return;
1031 + }
1032 +
882 1033 const formData = new FormData();
883 1034 formData.append( 'style_id', styleId );
884 1035 formData.append( 'style_name', newStyleName );
885 1036 doJsonPost( 'rename_style', formData ).then(
@@ -916,21 +1067,13 @@
916 1067 titleElement.textContent = newStyleName;
917 1068 }
918 1069
919 1070 /**
920 - * @param {string} templateKey
921 - * @return {HTMLElement} The template card element.
922 - */
923 - function getTemplateCard( templateKey ) {
924 - return document.getElementById( 'frm_template_style_cards_wrapper' ).querySelector( '.frm-style-card[data-template-key="' + templateKey + '"]' );
925 - }
926 -
927 - /**
928 1071 * @param {string} styleId
929 1072 * @return {HTMLElement} The card element.
930 1073 */
931 1074 function getCardByStyleId( styleId ) {
932 - const defaultCard = document.querySelector( '#frm_default_style_cards_wrapper > div[data-style-id="' + styleId + '"]' );
1075 + const defaultCard = document.querySelector( `#frm_default_style_cards_wrapper > div[data-style-id="${ styleId }"]` );
933 1076 if ( defaultCard ) {
934 1077 return defaultCard;
935 1078 }
936 1079 return Array.from( document.getElementById( 'frm_custom_style_cards_wrapper' ).children ).find( card => card.dataset.styleId === styleId );
@@ -941,9 +1084,9 @@
941 1084 * @param {string} iconId
942 1085 * @return {void}
943 1086 */
944 1087 function addIconToOption( option, iconId ) {
945 - const icon = frmDom.svg( { href: '#' + iconId } );
1088 + const icon = frmDom.svg( { href: `#${ iconId }` } );
946 1089 option.insertBefore( icon, option.firstChild );
947 1090 }
948 1091
949 1092 /**
@@ -1061,9 +1204,9 @@
1061 1204 defaultValues = JSON.parse( defaultValues );
1062 1205 }
1063 1206
1064 1207 for ( const key in defaultValues ) {
1065 - let targetInput = document.querySelector( 'input[name$="[' + key + ']"], select[name$="[' + key + ']"]' );
1208 + let targetInput = document.querySelector( `input[name$="[${ key }]"], select[name$="[${ key }]"]` );
1066 1209 if ( ! targetInput ) {
1067 1210 continue;
1068 1211 }
1069 1212
@@ -1068,9 +1211,9 @@
1068 1211 }
1069 1212
1070 1213 if ( 'radio' === targetInput.getAttribute( 'type' ) ) {
1071 1214 // Reset the repeater icon dropdown.
1072 - targetInput = document.querySelector( 'input[name$="[' + key + ']"][value="' + defaultValues[ key ] + '"]' );
1215 + targetInput = document.querySelector( `input[name$="[${ key }]"][value="${ defaultValues[ key ] }"]` );
1073 1216 if ( targetInput ) {
1074 1217 targetInput.checked = true;
1075 1218 jQuery( targetInput ).trigger( 'change' );
1076 1219 }
@@ -1084,8 +1227,9 @@
1084 1227 jQuery( targetInput ).trigger( 'change' );
1085 1228 }
1086 1229 }
1087 1230
1231 + resetCustomCSSEditor();
1088 1232 jQuery( '#frm_submit_style, #frm_auto_width' ).prop( 'checked', false );
1089 1233 jQuery( document.getElementById( 'frm_fieldset' ) ).trigger( 'change' );
1090 1234 showStyleResetSuccessMessage();
1091 1235 }
@@ -1090,8 +1234,23 @@
1090 1234 showStyleResetSuccessMessage();
1091 1235 }
1092 1236
1093 1237 /**
1238 + * Reset the custom CSS editor.
1239 + *
1240 + * @return {void}
1241 + */
1242 + function resetCustomCSSEditor() {
1243 + const checkbox = document.getElementById( 'frm_enable_single_style_custom_css' );
1244 + const editorWrapper = document.getElementById( 'frm_single_style_custom_css_editor' );
1245 + if ( ! checkbox || ! editorWrapper ) {
1246 + return;
1247 + }
1248 + checkbox.checked = false;
1249 + editorWrapper.classList.add( 'frm_hidden' );
1250 + }
1251 +
1252 + /**
1094 1253 * Reload Formidable CSS after a style is reset so the preview updates immediately without needing to reload the page.
1095 1254 *
1096 1255 * @return {void}
1097 1256 */
@@ -1103,21 +1262,21 @@
1103 1262
1104 1263 const newStyle = document.createElement( 'link' );
1105 1264 newStyle.rel = 'stylesheet';
1106 1265 newStyle.type = 'text/css';
1107 - newStyle.href = style.href + '&key=' + getAutoId(); // Make the URL unique so the old stylesheet doesn't get picked up by cache.
1266 + newStyle.href = `${ style.href }&key=${ getAutoId() }`; // Make the URL unique so the old stylesheet doesn't get picked up by cache.
1108 1267
1109 1268 // Listen for the new style to load before removing the old style to avoid having no styles while the new style is loading.
1110 1269 newStyle.addEventListener(
1111 1270 'load',
1112 1271 () => {
1113 - style.parentNode.removeChild( style );
1272 + style.remove();
1114 1273 newStyle.id = 'frm-custom-theme-css'; // Assign the old ID to the new style so it can be removed in the next reset action.
1115 1274 }
1116 1275 );
1117 1276
1118 1277 const head = document.getElementsByTagName( 'HEAD' )[ 0 ];
1119 - head.appendChild( newStyle );
1278 + head.append( newStyle );
1120 1279 }
1121 1280
1122 1281 /**
1123 1282 * @return {number} The auto ID.
@@ -1133,9 +1292,9 @@
1133 1292 * @return {HTMLElement} The dropdown item element.
1134 1293 */
1135 1294 function wrapDropdownItem( { anchor, type } ) {
1136 1295 return div( {
1137 - className: 'dropdown-item frm-' + type + '-style',
1296 + className: `dropdown-item frm-${ type }-style`,
1138 1297 child: anchor
1139 1298 } );
1140 1299 }
1141 1300
@@ -1163,29 +1322,86 @@
1163 1322 [ 'frm_field_height', 'frm_field_font_size', 'frm_field_pad' ].forEach( selector => {
1164 1323 document.getElementById( selector ).addEventListener( 'change', debouncedTextSquishCheck );
1165 1324 } );
1166 1325
1167 - jQuery( 'input.hex' ).wpColorPicker( {
1168 - change: function( event, ui ) {
1169 - let color = jQuery( this ).wpColorPicker( 'color' );
1326 + function detectColorFormat( value ) {
1327 + if ( value.startsWith( 'rgba' ) ) {
1328 + return 'rgba';
1329 + }
1330 + if ( value.startsWith( 'rgb' ) ) {
1331 + return 'rgb';
1332 + }
1333 + if ( value.startsWith( 'hsla' ) ) {
1334 + return 'hsla';
1335 + }
1336 + if ( value.startsWith( 'hsl' ) ) {
1337 + return 'hsl';
1338 + }
1339 + return 'hex';
1340 + }
1341 +
1342 + const nativeInputValueDescriptor = Object.getOwnPropertyDescriptor( HTMLInputElement.prototype, 'value' );
1343 +
1344 + jQuery( 'input.hex' ).each( function() {
1345 + this.dataset.colorFormat = detectColorFormat( this.value );
1346 +
1347 + // Prevent iris from overwriting non-hex formats with hex during color picking.
1348 + const input = this;
1349 + Object.defineProperty( input, 'value', {
1350 + get() {
1351 + return nativeInputValueDescriptor.get.call( this );
1352 + },
1353 + set( val ) {
1354 + const format = input.dataset.colorFormat;
1355 + if ( format && 'hex' !== format && /^#[0-9a-f]{3,8}$/i.test( val ) ) {
1356 + return;
1357 + }
1358 + nativeInputValueDescriptor.set.call( this, val );
1359 + },
1360 + configurable: true
1361 + } );
1362 + } ).on( 'keyup', function() {
1363 + const newFormat = detectColorFormat( this.value );
1364 + if ( this.dataset.colorFormat !== newFormat ) {
1365 + this.dataset.colorFormat = newFormat;
1366 + const container = this.closest( '.wp-picker-container' );
1367 + if ( container ) {
1368 + container.querySelector( '.wp-color-result-text' ).textContent = this.value;
1369 + }
1370 + debouncedColorChange( { target: this }, this.value );
1371 + }
1372 + } ).wpColorPicker( {
1373 + change( event, ui ) {
1374 + const input = event.target;
1375 + const format = input.dataset.colorFormat || 'hex';
1376 + let color;
1377 +
1170 1378 trackUnsavedChange();
1379 +
1171 1380 if ( ui.color._alpha < 1 ) {
1172 - // If there's transparency, use RGBA
1381 + input.dataset.colorFormat = 'rgba';
1173 1382 color = ui.color.toCSS( 'rgba' );
1383 + } else if ( 'hex' === format ) {
1384 + color = ui.color.toString();
1385 + } else {
1386 + color = ui.color.toCSS( format );
1174 1387 }
1388 +
1175 1389 debouncedColorChange( event, color );
1176 1390
1177 - if ( null !== event.target.getAttribute( 'data-alpha-color-type' ) ) {
1391 + input.value = color;
1392 +
1393 + if ( null !== input.getAttribute( 'data-alpha-color-type' ) ) {
1178 1394 debouncedPreviewUpdate();
1179 1395 return;
1180 1396 }
1181 1397
1182 - jQuery( event.target ).val( color ).trigger( 'change' );
1398 + debouncedPreviewUpdate();
1183 1399 }
1184 1400 } );
1185 1401 jQuery( '.wp-color-result-text' ).text( function( _, oldText ) {
1186 1402 const container = jQuery( this ).closest( '.wp-picker-container' );
1187 - if ( 'undefined' !== typeof container && container[ 0 ].parentElement.classList.contains( 'frm-colorpicker' ) ) {
1403 + if ( container !== undefined && container[ 0 ].parentElement.classList.contains( 'frm-colorpicker' ) ) {
1188 1404 return container[ 0 ].querySelector( '.wp-color-picker' ).value;
1189 1405 }
1190 1406 return oldText === 'Select Color' ? 'Select' : oldText;
1191 1407 } );
@@ -1234,9 +1450,9 @@
1234 1450 * @return {void}
1235 1451 */
1236 1452 function handleChangeStylingSuccess( css ) {
1237 1453 // Validate the string response. A valid output will include rules with .with_frm_style
1238 - if ( -1 === css.indexOf( '.with_frm_style' ) ) {
1454 + if ( ! css.includes( '.with_frm_style' ) ) {
1239 1455 // Handle error (possibly a permission error, or an outdated nonce).
1240 1456 alert( css );
1241 1457 return;
1242 1458 }
@@ -1296,9 +1512,9 @@
1296 1512 if ( select ) {
1297 1513 select.value = radio.value;
1298 1514 }
1299 1515
1300 - jQuery( btnGrp ).children( 'button' ).html( radio.nextElementSibling.innerHTML + ' <b class="caret"></b>' );
1516 + jQuery( btnGrp ).children( 'button' ).html( `${ radio.nextElementSibling.innerHTML } <b class="caret"></b>` );
1301 1517
1302 1518 const activeItem = btnGrp.querySelector( '.dropdown-item.active' );
1303 1519 if ( activeItem ) {
1304 1520 activeItem.classList.remove( 'active' );
@@ -1318,24 +1534,8 @@
1318 1534 }
1319 1535 }
1320 1536
1321 1537 /**
1322 - * @param {Event} event
1323 - */
1324 - function maybeCollapseSettings( event ) {
1325 - let expanded;
1326 - const sectionParent = event.target.parentElement;
1327 - if ( event.type === 'keydown' ) {
1328 - expanded = sectionParent.classList.toggle( 'open' );
1329 - jQuery( sectionParent.querySelector( '.accordion-section-content' ) ).toggle( ! expanded ).slideToggle( 150 ); // Animate toggle as in click/enter.
1330 - } else {
1331 - expanded = sectionParent.classList.contains( 'open' );
1332 - }
1333 -
1334 - event.target.setAttribute( 'aria-expanded', expanded );
1335 - }
1336 -
1337 - /**
1338 1538 * @param {HTMLElement} input
1339 1539 * @param {HTMLElement} container
1340 1540 * @return {void}
1341 1541 */
@@ -1385,9 +1585,9 @@
1385 1585 * @return {void}
1386 1586 */
1387 1587 function setPosClass() {
1388 1588 /*jshint validthis:true */
1389 - let value = this.value;
1589 + let { value } = this;
1390 1590 if ( value === 'none' ) {
1391 1591 value = 'top';
1392 1592 } else if ( value === 'no_label' ) {
1393 1593 value = 'none';
@@ -1398,9 +1598,9 @@
1398 1598 const shouldForceTopStyling = 'inside' === value && ( ! input || 'hidden' === input.type ); // We do not want file upload to use floating labels, or inline datepickers, which both use hidden inputs.
1399 1599 const currentValue = shouldForceTopStyling ? 'top' : value;
1400 1600
1401 1601 container.classList.remove( 'frm_top_container', 'frm_left_container', 'frm_right_container', 'frm_none_container', 'frm_inside_container' );
1402 - container.classList.add( 'frm_' + currentValue + '_container' );
1602 + container.classList.add( `frm_${ currentValue }_container` );
1403 1603
1404 1604 if ( 'inside' === currentValue ) {
1405 1605 checkFloatingLabelsForStyles( input, container );
1406 1606 }
@@ -1428,9 +1628,9 @@
1428 1628 *
1429 1629 * @return {void}
1430 1630 */
1431 1631 function fillMissingSignatureValidationFunction() {
1432 - if ( 'undefined' === typeof window.__FRMSIG || 'undefined' !== typeof window.frmFrontForm ) {
1632 + if ( window.__FRMSIG === undefined || window.frmFrontForm !== undefined ) {
1433 1633 return;
1434 1634 }
1435 1635
1436 1636 window.frmFrontForm = { validateFormSubmit: () => {} };
@@ -1469,9 +1669,9 @@
1469 1669 }
1470 1670
1471 1671 // Function to change the color of a select element
1472 1672 const changeSelectColor = select => {
1473 - if ( select.options[ select.selectedIndex ] && select.options[ select.selectedIndex ].classList.contains( 'frm-select-placeholder' ) ) {
1673 + if ( select.options[ select.selectedIndex ]?.classList.contains( 'frm-select-placeholder' ) ) {
1474 1674 select.style.setProperty( 'color', textColorDisabled, 'important' );
1475 1675 } else {
1476 1676 select.style.color = '';
1477 1677 }