| @@ -2,8 +2,9 @@ | ||
| 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 wp, frmDom, frmAdminBuild */ | |
| 6 | 7 | 'use strict'; |
| 7 | 8 | |
| 8 | 9 | if ( ! document.getElementById( 'frm_active_style_form' ) ) { |
| 9 | 10 | return; |
| @@ -8,10 +9,10 @@ | ||
| 8 | 9 | if ( ! document.getElementById( 'frm_active_style_form' ) ) { |
| 9 | 10 | return; |
| 10 | 11 | } |
| 11 | 12 | |
| 12 | - const { __, sprintf } = wp.i18n; | |
| 13 | - const state = { | |
| 13 | + const { __, sprintf } = wp.i18n; | |
| 14 | + const state = { | |
| 14 | 15 | showingSampleForm: document.getElementById( 'frm_active_style_form' ).classList.contains( 'frm_hidden' ), // boolean |
| 15 | 16 | unsavedChanges: false, // boolean |
| 16 | 17 | autoId: 0, // Number |
| 17 | 18 | // Track the value of the selected style ID on page (on the list page). |
| @@ -19,11 +20,11 @@ | ||
| 19 | 20 | // This way when you switch back to the initial value it doesn't count as a change. |
| 20 | 21 | initialSelectedStyleValue: false // String|false |
| 21 | 22 | }; |
| 22 | 23 | const { div, span, a, labelledTextInput, tag, svg, success } = frmDom; |
| 23 | - const { onClickPreventDefault } = frmDom.util; | |
| 24 | - const { maybeCreateModal, footerButton } = frmDom.modal; | |
| 25 | - const { doJsonPost } = frmDom.ajax; | |
| 24 | + const { onClickPreventDefault } = frmDom.util; | |
| 25 | + const { maybeCreateModal, footerButton } = frmDom.modal; | |
| 26 | + const { doJsonPost } = frmDom.ajax; | |
| 26 | 27 | |
| 27 | 28 | const isListPage = document.getElementsByClassName( 'frm-style-card' ).length > 0; |
| 28 | 29 | if ( isListPage ) { |
| 29 | 30 | initListPage(); |
| @@ -36,9 +37,9 @@ | ||
| 36 | 37 | /** |
| 37 | 38 | * These are shared events for both the edit/list views like the sample form toggle. |
| 38 | 39 | * This includes preview events, but also the update button click event handling for both views. |
| 39 | 40 | * |
| 40 | - * @return {void} | |
| 41 | + * @returns {void} | |
| 41 | 42 | */ |
| 42 | 43 | function initCommonEventListeners() { |
| 43 | 44 | document.addEventListener( 'click', handleCommonClickEvents ); |
| 44 | 45 | window.addEventListener( 'beforeunload', maybeConfirmExit ); |
| @@ -47,9 +48,9 @@ | ||
| 47 | 48 | |
| 48 | 49 | /** |
| 49 | 50 | * Initialize common functions required for the preview in both the edit and list views. |
| 50 | 51 | * |
| 51 | - * @return {void} | |
| 52 | + * @returns {void} | |
| 52 | 53 | */ |
| 53 | 54 | function initPreview() { |
| 54 | 55 | initFloatingLabels(); |
| 55 | 56 | fillMissingSignatureValidationFunction(); |
| @@ -61,103 +62,15 @@ | ||
| 61 | 62 | document.getElementById( 'frm_style_sidebar' ).classList.add( 'wp-core-ui' ); |
| 62 | 63 | |
| 63 | 64 | jQuery( document ).on( 'input change', 'input[data-frmrange]', initSliderPreview ); |
| 64 | 65 | |
| 65 | - initOptionLayoutPreview(); | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 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 | - /** | |
| 156 | 69 | * Initialize the slider functionality in the style preview. |
| 157 | 70 | * |
| 158 | 71 | * @param {HTMLElement} event |
| 159 | - * @return {void} | |
| 72 | + * @returns {void} | |
| 160 | 73 | */ |
| 161 | 74 | function initSliderPreview( event ) { |
| 162 | 75 | const wrapper = event.target.closest( '.frm_range_container' ); |
| 163 | 76 | if ( null === wrapper ) { |
| @@ -169,9 +82,9 @@ | ||
| 169 | 82 | /** |
| 170 | 83 | * Add the wp-core-ui class to the #wp-auth-check-wrap element. |
| 171 | 84 | * As this style isn't included on the body for the styler, the close button on the auth modal wasn't getting styled properly. |
| 172 | 85 | * |
| 173 | - * @return {void} | |
| 86 | + * @returns {void} | |
| 174 | 87 | */ |
| 175 | 88 | function fixWpAuthModal() { |
| 176 | 89 | const authWrap = document.getElementById( 'wp-auth-check-wrap' ); |
| 177 | 90 | if ( authWrap ) { |
| @@ -179,9 +92,9 @@ | ||
| 179 | 92 | } |
| 180 | 93 | } |
| 181 | 94 | |
| 182 | 95 | /** |
| 183 | - * @return {void} | |
| 96 | + * @returns {void} | |
| 184 | 97 | */ |
| 185 | 98 | function initListPage() { |
| 186 | 99 | document.addEventListener( 'click', handleClickEventsForListPage ); |
| 187 | 100 | // Add a timeout so Pro has a chance to add a filter first. |
| @@ -188,10 +101,10 @@ | ||
| 188 | 101 | // 0 does not always work in Google Chrome, so use 1. |
| 189 | 102 | setTimeout( addHamburgerMenusToCards, 1 ); |
| 190 | 103 | initDatepickerSample(); |
| 191 | 104 | |
| 192 | - const enableToggle = document.getElementById( 'frm_enable_styling' ); | |
| 193 | - const styleIdInput = getStyleIdInput(); | |
| 105 | + const enableToggle = document.getElementById( 'frm_enable_styling' ); | |
| 106 | + const styleIdInput = getStyleIdInput(); | |
| 194 | 107 | state.initialSelectedStyleValue = styleIdInput.value; |
| 195 | 108 | |
| 196 | 109 | enableToggle.addEventListener( 'change', handleEnableStylingToggleChange ); |
| 197 | 110 | |
| @@ -212,16 +125,16 @@ | ||
| 212 | 125 | |
| 213 | 126 | /** |
| 214 | 127 | * Handle pagination click events. |
| 215 | 128 | * |
| 216 | - * @return {void} | |
| 129 | + * @returns {void} | |
| 217 | 130 | */ |
| 218 | 131 | function initStyleCardPagination() { |
| 219 | 132 | document.querySelectorAll( '.frm-style-card-pagination' ).forEach( |
| 220 | 133 | pagination => { |
| 221 | - const wrapper = pagination.closest( '.frm-style-card-wrapper' ); | |
| 134 | + const wrapper = pagination.closest( '.frm-style-card-wrapper' ); | |
| 222 | 135 | const showAllAnchor = pagination.querySelector( '.frm-show-all-styles' ); |
| 223 | - let showingAll = false; | |
| 136 | + let showingAll = false; | |
| 224 | 137 | |
| 225 | 138 | onClickPreventDefault( |
| 226 | 139 | showAllAnchor, |
| 227 | 140 | () => { |
| @@ -237,9 +150,9 @@ | ||
| 237 | 150 | |
| 238 | 151 | wrapper.querySelectorAll( '.frm-style-card:nth-child(3) ~ .frm-style-card' ).forEach( |
| 239 | 152 | card => card.classList.add( 'frm_hidden' ) |
| 240 | 153 | ); |
| 241 | - const hiddenCount = wrapper.querySelectorAll( '.frm-style-card.frm_hidden' ).length; | |
| 154 | + const hiddenCount = wrapper.querySelectorAll( '.frm-style-card.frm_hidden' ).length; | |
| 242 | 155 | /* translators: %d: The number of hidden items to show. */ |
| 243 | 156 | showAllAnchor.textContent = sprintf( __( 'Show all (%d)', 'formidable' ), hiddenCount ); |
| 244 | 157 | } |
| 245 | 158 | ); |
| @@ -247,10 +160,10 @@ | ||
| 247 | 160 | ); |
| 248 | 161 | } |
| 249 | 162 | |
| 250 | 163 | /** |
| 251 | - * @param {string} labelPosition | |
| 252 | - * @return {void} Changes the label position in the preview. | |
| 164 | + * @param {String} labelPosition | |
| 165 | + * @returns {void} | |
| 253 | 166 | */ |
| 254 | 167 | function changeLabelPositionsInPreview( labelPosition ) { |
| 255 | 168 | const input = tag( 'input' ); |
| 256 | 169 | input.value = labelPosition; |
| @@ -257,9 +170,9 @@ | ||
| 257 | 170 | setPosClass.bind( input )(); |
| 258 | 171 | } |
| 259 | 172 | |
| 260 | 173 | /** |
| 261 | - * @return {HTMLElement} The active style card. | |
| 174 | + * @returns {HTMLElement} | |
| 262 | 175 | */ |
| 263 | 176 | function getActiveCard() { |
| 264 | 177 | return document.querySelector( '.frm-active-style-card' ); |
| 265 | 178 | } |
| @@ -269,9 +182,9 @@ | ||
| 269 | 182 | * The style ID value associated with the selected style card gets cleared. |
| 270 | 183 | * This is because disabling styles is linked to the custom_style option as well. |
| 271 | 184 | * |
| 272 | 185 | * @param {Event} event |
| 273 | - * @return {void} | |
| 186 | + * @returns {void} | |
| 274 | 187 | */ |
| 275 | 188 | function handleEnableStylingToggleChange( event ) { |
| 276 | 189 | const stylesEnabled = event.target.checked; |
| 277 | 190 | |
| @@ -303,21 +216,21 @@ | ||
| 303 | 216 | * All settings on the list page are mapped to the value of the styleIdInput. |
| 304 | 217 | * We track the value on load with state.initialSelectedStyleValue. |
| 305 | 218 | * Only consider unsaved changes on the page when this variable is no longer set to the original value. |
| 306 | 219 | * |
| 307 | - * @return {void} | |
| 220 | + * @returns {void} | |
| 308 | 221 | */ |
| 309 | 222 | function trackListPageChange() { |
| 310 | - const styleIdInput = getStyleIdInput(); | |
| 223 | + const styleIdInput = getStyleIdInput(); | |
| 311 | 224 | state.unsavedChanges = styleIdInput.value !== state.initialSelectedStyleValue; |
| 312 | 225 | } |
| 313 | 226 | |
| 314 | 227 | /** |
| 315 | 228 | * @param {boolean} on |
| 316 | - * @return {void} | |
| 229 | + * @returns {void} | |
| 317 | 230 | */ |
| 318 | 231 | function toggleFormidableStylingInPreviewForms( on ) { |
| 319 | - const preview = document.getElementById( 'frm_style_preview' ); | |
| 232 | + const preview = document.getElementById( 'frm_style_preview' ); | |
| 320 | 233 | const activeCard = getActiveCard(); |
| 321 | 234 | |
| 322 | 235 | let selector = '.frm_forms'; |
| 323 | 236 | if ( ! on ) { |
| @@ -332,9 +245,9 @@ | ||
| 332 | 245 | ); |
| 333 | 246 | } |
| 334 | 247 | |
| 335 | 248 | /** |
| 336 | - * @return {HTMLElement} The style ID input element. | |
| 249 | + * @returns {HTMLElement} | |
| 337 | 250 | */ |
| 338 | 251 | function getStyleIdInput() { |
| 339 | 252 | return document.getElementById( 'frm_style_list_form' ).querySelector( '[name="style_id"]' ); |
| 340 | 253 | } |
| @@ -340,12 +253,12 @@ | ||
| 340 | 253 | } |
| 341 | 254 | |
| 342 | 255 | /** |
| 343 | 256 | * @param {Event} event |
| 344 | - * @return {void} | |
| 257 | + * @returns {void} | |
| 345 | 258 | */ |
| 346 | 259 | function handleCommonClickEvents( event ) { |
| 347 | - const { target } = event; | |
| 260 | + const target = event.target; | |
| 348 | 261 | |
| 349 | 262 | if ( 'frm_toggle_sample_form' === target.id || target.closest( '#frm_toggle_sample_form' ) ) { |
| 350 | 263 | toggleSampleForm(); |
| 351 | 264 | return; |
| @@ -358,20 +271,20 @@ | ||
| 358 | 271 | } |
| 359 | 272 | |
| 360 | 273 | if ( target.classList.contains( 'frm-edit-style' ) || null !== target.closest( '.frm-edit-style' ) || 'frm_edit_style' === target.id ) { |
| 361 | 274 | modifyStylerUrl( target ); |
| 275 | + return; | |
| 362 | 276 | } |
| 363 | 277 | } |
| 364 | 278 | |
| 365 | 279 | /** |
| 366 | 280 | * This function is used to update the form action when switching from the advanced settings and quick-settings. |
| 367 | - * | |
| 368 | 281 | * @param {Object} target The submit button event target |
| 369 | 282 | * @return {void} |
| 370 | 283 | */ |
| 371 | 284 | function switchAdvancedSettingsFormAction( target ) { |
| 372 | 285 | const form = document.querySelector( '#frm_styling_form' ); |
| 373 | - if ( ! form ) { | |
| 286 | + if ( null === form ) { | |
| 374 | 287 | return; |
| 375 | 288 | } |
| 376 | 289 | if ( target.closest( 'a#frm_style_back_to_quick_settings' ) ) { |
| 377 | 290 | form.action = form.action.replace( '§ion=advanced-settings', '' ); |
| @@ -382,9 +295,9 @@ | ||
| 382 | 295 | } |
| 383 | 296 | } |
| 384 | 297 | |
| 385 | 298 | /** |
| 386 | - * @return {void} | |
| 299 | + * @returns {void} | |
| 387 | 300 | */ |
| 388 | 301 | function disablePreviewSubmitButtons() { |
| 389 | 302 | const preview = document.getElementById( 'frm_style_preview' ); |
| 390 | 303 | preview.querySelectorAll( 'form' ).forEach( |
| @@ -393,9 +306,9 @@ | ||
| 393 | 306 | /** |
| 394 | 307 | * Prevent form submit event. |
| 395 | 308 | * |
| 396 | 309 | * @param {Event} event |
| 397 | - * @return {false} Prevents the default action and stops the event from bubbling. | |
| 310 | + * @returns {false} | |
| 398 | 311 | */ |
| 399 | 312 | event => { |
| 400 | 313 | event.preventDefault(); |
| 401 | 314 | event.stopPropagation(); |
| @@ -406,15 +319,16 @@ | ||
| 406 | 319 | } |
| 407 | 320 | |
| 408 | 321 | /** |
| 409 | 322 | * @param {Event} event |
| 410 | - * @return {void} | |
| 323 | + * @returns {void} | |
| 411 | 324 | */ |
| 412 | 325 | function handleClickEventsForListPage( event ) { |
| 413 | - const { target } = event; | |
| 326 | + const target = event.target; | |
| 414 | 327 | |
| 415 | 328 | if ( target.classList.contains( 'frm-style-card' ) || target.closest( '.frm-style-card' ) ) { |
| 416 | 329 | handleStyleCardClick( event ); |
| 330 | + return; | |
| 417 | 331 | } |
| 418 | 332 | } |
| 419 | 333 | |
| 420 | 334 | /** |
| @@ -421,12 +335,12 @@ | ||
| 421 | 335 | * When a style card is clicked, the preview is updated. |
| 422 | 336 | * If the Update button is clicked after selecting a style card, the active card will be saved as the target form's style. |
| 423 | 337 | * |
| 424 | 338 | * @param {Event} event |
| 425 | - * @return {void} | |
| 339 | + * @returns {void} | |
| 426 | 340 | */ |
| 427 | 341 | function handleStyleCardClick( event ) { |
| 428 | - const { target } = event; | |
| 342 | + const target = event.target; | |
| 429 | 343 | |
| 430 | 344 | if ( target.closest( '.dropdown' ) ) { |
| 431 | 345 | // Ignore the hamburger menu inside of the card. |
| 432 | 346 | return; |
| @@ -431,9 +345,9 @@ | ||
| 431 | 345 | // Ignore the hamburger menu inside of the card. |
| 432 | 346 | return; |
| 433 | 347 | } |
| 434 | 348 | |
| 435 | - const card = target.classList.contains( 'frm-style-card' ) ? target : target.closest( '.frm-style-card' ); | |
| 349 | + const card = target.classList.contains( 'frm-style-card' ) ? target : target.closest( '.frm-style-card' ); | |
| 436 | 350 | const cardIsLocked = card.classList.contains( 'frm-locked-style' ); |
| 437 | 351 | |
| 438 | 352 | if ( cardIsLocked ) { |
| 439 | 353 | maybeCreateStyleTemplateModal( card ); |
| @@ -439,11 +353,11 @@ | ||
| 439 | 353 | maybeCreateStyleTemplateModal( card ); |
| 440 | 354 | return; // Exit early as we're not actually selecting a locked template for preview. |
| 441 | 355 | } |
| 442 | 356 | |
| 443 | - const previewArea = document.getElementById( 'frm_style_preview' ); | |
| 444 | - const activeCard = document.querySelector( '.frm-active-style-card' ); | |
| 445 | - const sampleForm = document.getElementById( 'frm_sample_form' ).querySelector( '.frm_forms' ); | |
| 357 | + const previewArea = document.getElementById( 'frm_style_preview' ); | |
| 358 | + const activeCard = document.querySelector( '.frm-active-style-card' ); | |
| 359 | + const sampleForm = document.getElementById( 'frm_sample_form' ).querySelector( '.frm_forms' ); | |
| 446 | 360 | const styleIdInput = getStyleIdInput(); |
| 447 | 361 | |
| 448 | 362 | disableLabelTransitions(); |
| 449 | 363 | |
| @@ -459,16 +373,18 @@ | ||
| 459 | 373 | |
| 460 | 374 | sampleForm.classList.remove( activeCard.dataset.classname ); |
| 461 | 375 | sampleForm.classList.add( card.dataset.classname ); |
| 462 | 376 | |
| 463 | - // cardIsLocked is always false here due to early return above. | |
| 464 | - styleIdInput.value = card.dataset.styleId; | |
| 465 | - trackListPageChange(); | |
| 377 | + if ( ! cardIsLocked ) { | |
| 378 | + // Don't update the form when a locked card is clicked. | |
| 379 | + styleIdInput.value = card.dataset.styleId; | |
| 380 | + trackListPageChange(); | |
| 381 | + } | |
| 466 | 382 | |
| 467 | 383 | setTimeout( enableLabelTransitions, 1 ); |
| 468 | 384 | |
| 469 | 385 | // 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). |
| 470 | - const editButton = document.getElementById( 'frm_edit_style' ); | |
| 386 | + const editButton = document.getElementById( 'frm_edit_style' ); | |
| 471 | 387 | const showEditButton = null !== card.querySelector( '.frm-style-card-info' ); // Only the "Applied style" has card info. |
| 472 | 388 | editButton.classList.toggle( 'frm_hidden', ! showEditButton ); |
| 473 | 389 | |
| 474 | 390 | changeLabelPositionsInPreview( card.dataset.labelPosition ); |
| @@ -473,21 +389,21 @@ | ||
| 473 | 389 | |
| 474 | 390 | changeLabelPositionsInPreview( card.dataset.labelPosition ); |
| 475 | 391 | |
| 476 | 392 | // Trigger an action here so Pro can handle template preview updates on card click. |
| 477 | - const hookName = 'frm_style_card_click'; | |
| 478 | - const hookArgs = { card, styleIdInput }; | |
| 393 | + const hookName = 'frm_style_card_click'; | |
| 394 | + const hookArgs = { card, styleIdInput }; | |
| 479 | 395 | wp.hooks.doAction( hookName, hookArgs ); |
| 480 | 396 | } |
| 481 | 397 | |
| 482 | 398 | /** |
| 483 | 399 | * @param {HTMLElement} card |
| 484 | - * @return {HTMLElement} The modal element. | |
| 400 | + * @returns {HTMLElement} | |
| 485 | 401 | */ |
| 486 | 402 | function maybeCreateStyleTemplateModal( card ) { |
| 487 | - const titleElement = card.querySelector( '.frm-style-card-title' ); | |
| 403 | + const titleElement = card.querySelector( '.frm-style-card-title' ); | |
| 488 | 404 | const templateTitle = titleElement.textContent; |
| 489 | - const modal = maybeCreateModal( | |
| 405 | + const modal = maybeCreateModal( | |
| 490 | 406 | 'frm_style_template_modal', |
| 491 | 407 | { |
| 492 | 408 | content: getStyleTemplateModalContent( card ), |
| 493 | 409 | footer: getStyleTemplateModalFooter( card ) |
| @@ -498,15 +414,15 @@ | ||
| 498 | 414 | } |
| 499 | 415 | |
| 500 | 416 | /** |
| 501 | 417 | * @param {HTMLElement} card |
| 502 | - * @return {HTMLElement} The modal content element. | |
| 418 | + * @returns {HTMLElement} | |
| 503 | 419 | */ |
| 504 | 420 | function getStyleTemplateModalContent( card ) { |
| 505 | 421 | const children = []; |
| 506 | 422 | |
| 507 | 423 | children.push( |
| 508 | - div( { | |
| 424 | + div({ | |
| 509 | 425 | className: 'frm_warning_style', |
| 510 | 426 | children: [ |
| 511 | 427 | span( |
| 512 | 428 | /* translators: %s: The required license type (ie. Plus, Business, or Elite) */ |
| @@ -511,48 +427,48 @@ | ||
| 511 | 427 | span( |
| 512 | 428 | /* translators: %s: The required license type (ie. Plus, Business, or Elite) */ |
| 513 | 429 | sprintf( __( 'Access to this style requires the %s plan.', 'formidable' ), card.dataset.requires ) |
| 514 | 430 | ), |
| 515 | - a( { | |
| 431 | + a({ | |
| 516 | 432 | text: getUpgradeNowText(), |
| 517 | 433 | href: card.dataset.upgradeUrl, |
| 518 | 434 | target: '_blank' |
| 519 | - } ) | |
| 435 | + }) | |
| 520 | 436 | ] |
| 521 | - } ) | |
| 437 | + }) | |
| 522 | 438 | ); |
| 523 | 439 | |
| 524 | - return div( { children } ); | |
| 440 | + return div({ children }); | |
| 525 | 441 | } |
| 526 | 442 | |
| 527 | 443 | /** |
| 528 | 444 | * @param {HTMLElement} card |
| 529 | - * @return {HTMLElement} The modal footer element. | |
| 445 | + * @returns {HTMLElement} | |
| 530 | 446 | */ |
| 531 | 447 | function getStyleTemplateModalFooter( card ) { |
| 532 | - const viewDemoSiteButton = footerButton( { | |
| 448 | + const viewDemoSiteButton = footerButton({ | |
| 533 | 449 | text: __( 'Learn More', 'formidable' ), |
| 534 | 450 | buttonType: 'secondary' |
| 535 | - } ); | |
| 451 | + }); | |
| 536 | 452 | viewDemoSiteButton.href = card.dataset.upgradeUrl; |
| 537 | 453 | viewDemoSiteButton.target = '_blank'; |
| 538 | 454 | |
| 539 | - const primaryActionButton = footerButton( { | |
| 455 | + let primaryActionButton = footerButton({ | |
| 540 | 456 | text: getUpgradeNowText(), |
| 541 | 457 | buttonType: 'primary' |
| 542 | - } ); | |
| 458 | + }); | |
| 543 | 459 | |
| 544 | 460 | primaryActionButton.classList.remove( 'dismiss' ); |
| 545 | 461 | primaryActionButton.setAttribute( 'href', card.dataset.upgradeUrl ); |
| 546 | 462 | primaryActionButton.target = '_blank'; |
| 547 | 463 | |
| 548 | - return div( { | |
| 464 | + return div({ | |
| 549 | 465 | children: [ viewDemoSiteButton, primaryActionButton ] |
| 550 | - } ); | |
| 466 | + }); | |
| 551 | 467 | } |
| 552 | 468 | |
| 553 | 469 | /** |
| 554 | - * @return {string} The upgrade now text. | |
| 470 | + * @returns {String} | |
| 555 | 471 | */ |
| 556 | 472 | function getUpgradeNowText() { |
| 557 | 473 | return __( 'Upgrade Now', 'formidable' ); |
| 558 | 474 | } |
| @@ -560,9 +476,9 @@ | ||
| 560 | 476 | /** |
| 561 | 477 | * Track an unsaved change on the edit page. |
| 562 | 478 | * This is included in the frmStylerFunctions global so unsaved changes can be tracked in Pro as well. |
| 563 | 479 | * |
| 564 | - * @return {void} | |
| 480 | + * @returns {void} | |
| 565 | 481 | */ |
| 566 | 482 | function trackUnsavedChange() { |
| 567 | 483 | state.unsavedChanges = true; |
| 568 | 484 | } |
| @@ -570,9 +486,9 @@ | ||
| 570 | 486 | /** |
| 571 | 487 | * Possibly prevent leaving the page if there are unsaved changes. |
| 572 | 488 | * |
| 573 | 489 | * @param {Event} event |
| 574 | - * @return {void} | |
| 490 | + * @returns {void} | |
| 575 | 491 | */ |
| 576 | 492 | function maybeConfirmExit( event ) { |
| 577 | 493 | if ( ! state.unsavedChanges ) { |
| 578 | 494 | return; |
| @@ -584,9 +500,9 @@ | ||
| 584 | 500 | |
| 585 | 501 | /** |
| 586 | 502 | * Floating labels have a transition style. Turn it off temporarily when switching between cards to avoid a transition between two different style classes. |
| 587 | 503 | * |
| 588 | - * @return {void} | |
| 504 | + * @returns {void} | |
| 589 | 505 | */ |
| 590 | 506 | function disableLabelTransitions() { |
| 591 | 507 | setLabelTransitionStyle( 'none' ); |
| 592 | 508 | } |
| @@ -591,9 +507,9 @@ | ||
| 591 | 507 | setLabelTransitionStyle( 'none' ); |
| 592 | 508 | } |
| 593 | 509 | |
| 594 | 510 | /** |
| 595 | - * @return {void} | |
| 511 | + * @returns {void} | |
| 596 | 512 | */ |
| 597 | 513 | function enableLabelTransitions() { |
| 598 | 514 | setLabelTransitionStyle( '' ); |
| 599 | 515 | } |
| @@ -598,10 +514,10 @@ | ||
| 598 | 514 | setLabelTransitionStyle( '' ); |
| 599 | 515 | } |
| 600 | 516 | |
| 601 | 517 | /** |
| 602 | - * @param {string} value | |
| 603 | - * @return {void} | |
| 518 | + * @param {String} value | |
| 519 | + * @returns {void} | |
| 604 | 520 | */ |
| 605 | 521 | function setLabelTransitionStyle( value ) { |
| 606 | 522 | document.getElementById( 'frm_style_preview' ).querySelectorAll( '.frm_inside_container' ).forEach( |
| 607 | 523 | container => container.querySelector( 'label' ).style.transition = value |
| @@ -608,9 +524,9 @@ | ||
| 608 | 524 | ); |
| 609 | 525 | } |
| 610 | 526 | |
| 611 | 527 | /** |
| 612 | - * @return {void} | |
| 528 | + * @returns {void} | |
| 613 | 529 | */ |
| 614 | 530 | function toggleSampleForm() { |
| 615 | 531 | state.showingSampleForm = ! state.showingSampleForm; |
| 616 | 532 | document.getElementById( 'frm_active_style_form' ).classList.toggle( 'frm_hidden', state.showingSampleForm ); |
| @@ -617,9 +533,9 @@ | ||
| 617 | 533 | document.getElementById( 'frm_toggle_sample_form' ).querySelector( 'span' ).textContent = state.showingSampleForm ? __( 'View my form', 'formidable' ) : __( 'View sample form', 'formidable' ); |
| 618 | 534 | } |
| 619 | 535 | |
| 620 | 536 | /** |
| 621 | - * @return {void} | |
| 537 | + * @returns {void} | |
| 622 | 538 | */ |
| 623 | 539 | function handleUpdateClick() { |
| 624 | 540 | state.unsavedChanges = false; // Prevent the saved changes pop up from triggering when submitting the form. |
| 625 | 541 | |
| @@ -640,9 +556,9 @@ | ||
| 640 | 556 | * Maybe modify an anchor's URL on click. |
| 641 | 557 | * If the sample form toggle is active, we want to pass that as a query parameter so we know to default to the sample form on load. |
| 642 | 558 | * |
| 643 | 559 | * @param {HTMLElement} clickTarget |
| 644 | - * @return {void} | |
| 560 | + * @returns {void} | |
| 645 | 561 | */ |
| 646 | 562 | function modifyStylerUrl( clickTarget ) { |
| 647 | 563 | if ( ! state.showingSampleForm ) { |
| 648 | 564 | // Don't change the URL if it is not a sample form. |
| @@ -649,15 +565,15 @@ | ||
| 649 | 565 | return; |
| 650 | 566 | } |
| 651 | 567 | |
| 652 | 568 | const anchor = clickTarget.hasAttribute( 'href' ) ? clickTarget : clickTarget.querySelector( 'a[href]' ); |
| 653 | - anchor.setAttribute( 'href', `${ anchor.getAttribute( 'href' ) }&sample=1` ); | |
| 569 | + anchor.setAttribute( 'href', anchor.getAttribute( 'href' ) + '&sample=1' ); | |
| 654 | 570 | } |
| 655 | 571 | |
| 656 | 572 | /** |
| 657 | 573 | * Add menu dropdowns to style cards dynamically on load. |
| 658 | 574 | * |
| 659 | - * @return {void} | |
| 575 | + * @returns {void} | |
| 660 | 576 | */ |
| 661 | 577 | function addHamburgerMenusToCards() { |
| 662 | 578 | const cards = Array.from( document.getElementsByClassName( 'frm-style-card' ) ); |
| 663 | 579 | cards.forEach( card => maybeAddMenuToCard( card ) ); |
| @@ -663,10 +579,10 @@ | ||
| 663 | 579 | cards.forEach( card => maybeAddMenuToCard( card ) ); |
| 664 | 580 | } |
| 665 | 581 | |
| 666 | 582 | /** |
| 667 | - * @param {HTMLElement} card | |
| 668 | - * @return {void} | |
| 583 | + * @param {HTMLlement} card | |
| 584 | + * @returns {void} | |
| 669 | 585 | */ |
| 670 | 586 | function maybeAddMenuToCard( card ) { |
| 671 | 587 | if ( ! shouldAddMenuToCard( card ) ) { |
| 672 | 588 | return; |
| @@ -671,16 +587,16 @@ | ||
| 671 | 587 | if ( ! shouldAddMenuToCard( card ) ) { |
| 672 | 588 | return; |
| 673 | 589 | } |
| 674 | 590 | |
| 675 | - card.append( getHamburgerMenu( card.dataset ) ); | |
| 591 | + card.appendChild( getHamburgerMenu( card.dataset ) ); | |
| 676 | 592 | } |
| 677 | 593 | |
| 678 | 594 | /** |
| 679 | 595 | * Avoid adding a menu to an upsell card or a template card. |
| 680 | 596 | * |
| 681 | - * @param {HTMLElement} card | |
| 682 | - * @return {boolean} Whether to add a menu to the card. | |
| 597 | + * @param {HTMLlement} card | |
| 598 | + * @returns {boolean} | |
| 683 | 599 | */ |
| 684 | 600 | function shouldAddMenuToCard( card ) { |
| 685 | 601 | return 'frm_template_style_cards_wrapper' !== card.parentNode.id || ! card.classList.contains( 'frm-locked-style' ); |
| 686 | 602 | } |
| @@ -685,9 +601,9 @@ | ||
| 685 | 601 | return 'frm_template_style_cards_wrapper' !== card.parentNode.id || ! card.classList.contains( 'frm-locked-style' ); |
| 686 | 602 | } |
| 687 | 603 | |
| 688 | 604 | /** |
| 689 | - * @return {void} | |
| 605 | + * @returns {void} | |
| 690 | 606 | */ |
| 691 | 607 | function addHamburgerMenuForEditPage() { |
| 692 | 608 | const styleName = document.getElementById( 'frm_style_name' ); |
| 693 | 609 | if ( ! styleName ) { |
| @@ -695,9 +611,9 @@ | ||
| 695 | 611 | } |
| 696 | 612 | |
| 697 | 613 | const styleId = document.getElementById( 'frm_styling_form' ).querySelector( 'input[name="ID"]' ).value; |
| 698 | 614 | |
| 699 | - const hamburgerMenu = getHamburgerMenu( { styleId } ); | |
| 615 | + const hamburgerMenu = getHamburgerMenu({ styleId }); | |
| 700 | 616 | hamburgerMenu.classList.add( 'alignright' ); |
| 701 | 617 | styleName.parentNode.insertBefore( hamburgerMenu, styleName ); |
| 702 | 618 | } |
| 703 | 619 | |
| @@ -704,34 +620,34 @@ | ||
| 704 | 620 | /** |
| 705 | 621 | * Get a dropdown and the "hamburger" stacked dot menu trigger for a single style card. |
| 706 | 622 | * |
| 707 | 623 | * @param {DOMStringMap} data { |
| 708 | - * @type {string} editUrl | |
| 709 | - * @type {string} styleId | |
| 710 | - * @type {string} labelPosition | |
| 711 | - * @type {string} classname | |
| 624 | + * @type {String} editUrl | |
| 625 | + * @type {String} styleId | |
| 626 | + * @type {String} labelPosition | |
| 627 | + * @type {String} classname | |
| 712 | 628 | * } |
| 713 | - * @return {HTMLElement} The hamburger menu element. | |
| 629 | + * @returns {HTMLElement} | |
| 714 | 630 | */ |
| 715 | 631 | function getHamburgerMenu( data ) { |
| 716 | - const hamburgerMenu = a( { | |
| 632 | + const hamburgerMenu = a({ | |
| 717 | 633 | className: 'frm-dropdown-toggle dropdown-toggle', |
| 718 | - child: svg( { href: '#frm_thick_more_vert_icon' } ) | |
| 719 | - } ); | |
| 720 | - hamburgerMenu.setAttribute( 'data-bs-toggle', 'dropdown' ); | |
| 721 | - hamburgerMenu.setAttribute( 'data-bs-container', 'body' ); | |
| 634 | + child: svg({ href: '#frm_thick_more_vert_icon' }) | |
| 635 | + }); | |
| 636 | + hamburgerMenu.setAttribute( 'data-toggle', 'dropdown' ); | |
| 637 | + hamburgerMenu.setAttribute( 'data-container', 'body' ); | |
| 722 | 638 | hamburgerMenu.setAttribute( 'role', 'button' ); |
| 723 | 639 | hamburgerMenu.setAttribute( 'tabindex', 0 ); |
| 724 | 640 | |
| 725 | - const isTemplate = data.templateKey !== undefined; | |
| 641 | + const isTemplate = 'undefined' !== typeof data.templateKey; | |
| 726 | 642 | let dropdownMenuOptions = []; |
| 727 | 643 | |
| 728 | 644 | if ( isListPage ) { |
| 729 | - const applyOption = a( { | |
| 645 | + const applyOption = a({ | |
| 730 | 646 | text: isTemplate ? __( 'Install and apply', 'formidable' ) : __( 'Apply', 'formidable' ) |
| 731 | - } ); | |
| 647 | + }); | |
| 732 | 648 | addIconToOption( applyOption, 'frm_save_icon' ); |
| 733 | - dropdownMenuOptions.push( { anchor: applyOption, type: 'apply' } ); | |
| 649 | + dropdownMenuOptions.push({ anchor: applyOption, type: 'apply' }); | |
| 734 | 650 | onClickPreventDefault( applyOption, handleApplyOptionClick ); |
| 735 | 651 | } |
| 736 | 652 | |
| 737 | 653 | if ( ! isTemplate ) { |
| @@ -736,19 +652,19 @@ | ||
| 736 | 652 | |
| 737 | 653 | if ( ! isTemplate ) { |
| 738 | 654 | if ( 'string' === typeof data.editUrl ) { |
| 739 | 655 | // The Edit option is not included on the Edit page. |
| 740 | - const editOption = a( { | |
| 656 | + const editOption = a({ | |
| 741 | 657 | text: __( 'Edit', 'formidable' ), |
| 742 | 658 | href: data.editUrl |
| 743 | - } ); | |
| 659 | + }); | |
| 744 | 660 | addIconToOption( editOption, 'frm_pencil_icon' ); |
| 745 | - dropdownMenuOptions.push( { anchor: editOption, type: 'edit' } ); | |
| 661 | + dropdownMenuOptions.push({ anchor: editOption, type: 'edit' }); | |
| 746 | 662 | } |
| 747 | 663 | |
| 748 | - const resetOption = a( { | |
| 664 | + const resetOption = a({ | |
| 749 | 665 | text: __( 'Reset to Defaults', 'formidable' ) |
| 750 | - } ); | |
| 666 | + }); | |
| 751 | 667 | addIconToOption( resetOption, 'frm_repeater_icon' ); |
| 752 | 668 | onClickPreventDefault( resetOption, () => confirmResetStyle( data.styleId ) ); |
| 753 | 669 | |
| 754 | 670 | dropdownMenuOptions.push( |
| @@ -756,10 +672,10 @@ | ||
| 756 | 672 | { anchor: resetOption, type: 'reset' } |
| 757 | 673 | ); |
| 758 | 674 | } |
| 759 | 675 | |
| 760 | - const hookName = 'frm_style_card_dropdown_options'; | |
| 761 | - const hookArgs = { data, addIconToOption, isTemplate }; | |
| 676 | + const hookName = 'frm_style_card_dropdown_options'; | |
| 677 | + const hookArgs = { data, addIconToOption, isTemplate }; | |
| 762 | 678 | dropdownMenuOptions = wp.hooks.applyFilters( hookName, dropdownMenuOptions, hookArgs ); |
| 763 | 679 | |
| 764 | 680 | if ( isListPage && ! isTemplate ) { |
| 765 | 681 | maybeAddDuplicateUpsell( dropdownMenuOptions ); |
| @@ -764,33 +680,33 @@ | ||
| 764 | 680 | if ( isListPage && ! isTemplate ) { |
| 765 | 681 | maybeAddDuplicateUpsell( dropdownMenuOptions ); |
| 766 | 682 | } |
| 767 | 683 | |
| 768 | - const dropdownMenu = div( { | |
| 684 | + const dropdownMenu = div({ | |
| 769 | 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). |
| 770 | 686 | className: 'frm-dropdown-menu frm-style-options-menu frm-p-1', |
| 771 | 687 | children: dropdownMenuOptions.map( wrapDropdownItem ) |
| 772 | - } ); | |
| 688 | + }); | |
| 773 | 689 | |
| 774 | 690 | const isRtl = document.body.classList.contains( 'rtl' ); |
| 775 | - dropdownMenu.classList.add( `dropdown-menu-${ isRtl ? 'left' : 'right' }` ); | |
| 691 | + dropdownMenu.classList.add( 'dropdown-menu-' + ( isRtl ? 'left' : 'right' ) ); | |
| 776 | 692 | |
| 777 | 693 | dropdownMenu.setAttribute( 'role', 'menu' ); |
| 778 | 694 | |
| 779 | - return div( { | |
| 695 | + return div({ | |
| 780 | 696 | className: 'dropdown frm_wrap', // The .frm_wrap class prevents a blue outline on the active dropdown trigger. |
| 781 | 697 | children: [ hamburgerMenu, dropdownMenu ] |
| 782 | - } ); | |
| 698 | + }); | |
| 783 | 699 | } |
| 784 | 700 | |
| 785 | 701 | /** |
| 786 | 702 | * @param {Array} dropdownMenuOptions |
| 787 | - * @return {void} | |
| 703 | + * @returns {void} | |
| 788 | 704 | */ |
| 789 | 705 | function maybeAddDuplicateUpsell( dropdownMenuOptions ) { |
| 790 | 706 | let duplicateOptionExists = false; |
| 791 | 707 | for ( let i = 0; i < dropdownMenuOptions.length; ++i ) { |
| 792 | - if ( dropdownMenuOptions[ i ].type === 'duplicate' ) { | |
| 708 | + if ( dropdownMenuOptions[i].type === 'duplicate' ) { | |
| 793 | 709 | duplicateOptionExists = true; |
| 794 | 710 | break; |
| 795 | 711 | } |
| 796 | 712 | } |
| @@ -798,12 +714,12 @@ | ||
| 798 | 714 | if ( duplicateOptionExists ) { |
| 799 | 715 | return; |
| 800 | 716 | } |
| 801 | 717 | |
| 802 | - const duplicateUpsell = a( { | |
| 718 | + const duplicateUpsell = a({ | |
| 803 | 719 | text: __( 'Duplicate', 'formidable' ), |
| 804 | 720 | className: 'frm_noallow' |
| 805 | - } ); | |
| 721 | + }); | |
| 806 | 722 | addIconToOption( duplicateUpsell, 'frm_clone_icon' ); |
| 807 | 723 | onClickPreventDefault( duplicateUpsell, () => document.getElementById( 'frm_new_style_trigger' ).click() ); |
| 808 | 724 | const upsellOption = { anchor: duplicateUpsell, type: 'duplicate' }; |
| 809 | 725 | dropdownMenuOptions.splice( 3, 0, upsellOption ); |
| @@ -810,13 +726,13 @@ | ||
| 810 | 726 | } |
| 811 | 727 | |
| 812 | 728 | /** |
| 813 | 729 | * @param {Event} event |
| 814 | - * @return {void} | |
| 730 | + * @returns {void} | |
| 815 | 731 | */ |
| 816 | 732 | function handleApplyOptionClick( event ) { |
| 817 | 733 | const option = event.target; |
| 818 | - const card = option.closest( '.frm-style-card' ); | |
| 734 | + const card = option.closest( '.frm-style-card' ); | |
| 819 | 735 | if ( ! card ) { |
| 820 | 736 | return; |
| 821 | 737 | } |
| 822 | 738 | |
| @@ -824,14 +740,14 @@ | ||
| 824 | 740 | handleUpdateClick(); |
| 825 | 741 | } |
| 826 | 742 | |
| 827 | 743 | /** |
| 828 | - * @param {string} styleId | |
| 829 | - * @return {HTMLElement} The rename option element. | |
| 744 | + * @param {String} styleId | |
| 745 | + * @returns {HTMLElement} | |
| 830 | 746 | */ |
| 831 | 747 | function getRenameOption( styleId ) { |
| 832 | 748 | const renameOption = a( __( 'Rename', 'formidable' ) ); |
| 833 | - addIconToOption( renameOption, 'frm_signature2_icon' ); | |
| 749 | + addIconToOption( renameOption, 'frm_signature_icon' ); | |
| 834 | 750 | |
| 835 | 751 | let titleTarget; |
| 836 | 752 | |
| 837 | 753 | // Depending on the page we're pulling the text from an existing element on the page. |
| @@ -859,11 +775,11 @@ | ||
| 859 | 775 | return renameOption; |
| 860 | 776 | } |
| 861 | 777 | |
| 862 | 778 | /** |
| 863 | - * @param {string} id | |
| 779 | + * @param {String} id | |
| 864 | 780 | * @param {Object} args |
| 865 | - * @return {HTMLElement} The modal element. | |
| 781 | + * @returns {HTMLElement} | |
| 866 | 782 | */ |
| 867 | 783 | function stylerModal( id, args ) { |
| 868 | 784 | const modal = maybeCreateModal( id, args ); |
| 869 | 785 | // Include both wp-core-ui and frm-white-body on the modal. |
| @@ -876,11 +792,11 @@ | ||
| 876 | 792 | /** |
| 877 | 793 | * Get modal content with just a "Style Name" input. |
| 878 | 794 | * This is used for New style, Duplicate style, and for Rename style. |
| 879 | 795 | * |
| 880 | - * @param {string} context | |
| 881 | - * @param {string|undefined} value | |
| 882 | - * @return {HTMLElement} The modal content element. | |
| 796 | + * @param {String} context | |
| 797 | + * @param {String|undefined} value | |
| 798 | + * @returns {HTMLElement} | |
| 883 | 799 | */ |
| 884 | 800 | function getStyleInputNameModalContent( context, value ) { |
| 885 | 801 | // Create a form so we can listen to Enter key presses that trigger a form submit event. |
| 886 | 802 | const form = tag( |
| @@ -885,9 +801,9 @@ | ||
| 885 | 801 | // Create a form so we can listen to Enter key presses that trigger a form submit event. |
| 886 | 802 | const form = tag( |
| 887 | 803 | 'form', |
| 888 | 804 | { |
| 889 | - child: labelledTextInput( `frm_${ context }_style_name_input`, __( 'Style name', 'formidable' ), 'style_name' ) | |
| 805 | + child: labelledTextInput( 'frm_' + context + '_style_name_input', __( 'Style name', 'formidable' ), 'style_name' ) | |
| 890 | 806 | } |
| 891 | 807 | ); |
| 892 | 808 | form.addEventListener( |
| 893 | 809 | 'submit', |
| @@ -892,9 +808,9 @@ | ||
| 892 | 808 | form.addEventListener( |
| 893 | 809 | 'submit', |
| 894 | 810 | /** |
| 895 | 811 | * @param {Event} event |
| 896 | - * @return {false} Prevents the default action and stops the event from bubbling. | |
| 812 | + * @returns {false} | |
| 897 | 813 | */ |
| 898 | 814 | event => { |
| 899 | 815 | // Prevent the form in the modal from submitting and trigger the click button in the modal footer instead. |
| 900 | 816 | event.preventDefault(); |
| @@ -904,9 +820,9 @@ | ||
| 904 | 820 | |
| 905 | 821 | return false; |
| 906 | 822 | } |
| 907 | 823 | ); |
| 908 | - const content = div( { child: form } ); | |
| 824 | + const content = div({ child: form }); | |
| 909 | 825 | content.style.padding = '20px'; |
| 910 | 826 | content.querySelector( 'label' ).style.lineHeight = 1.5; |
| 911 | 827 | |
| 912 | 828 | const styleNameInput = content.querySelector( 'input' ); |
| @@ -931,32 +847,32 @@ | ||
| 931 | 847 | return content; |
| 932 | 848 | } |
| 933 | 849 | |
| 934 | 850 | /** |
| 935 | - * @param {string} styleId | |
| 936 | - * @return {HTMLElement} The modal footer element. | |
| 851 | + * @param {String} styleId | |
| 852 | + * @returns {HTMLELement} | |
| 937 | 853 | */ |
| 938 | - function getRenameStyleModalFooter( styleId ) { | |
| 939 | - const cancelButton = footerButton( { text: __( 'Cancel', 'formidable' ), buttonType: 'cancel' } ); | |
| 854 | + function getRenameStyleModalFooter( styleId ) { | |
| 855 | + const cancelButton = footerButton({ text: __( 'Cancel', 'formidable' ), buttonType: 'cancel' }); | |
| 940 | 856 | cancelButton.classList.add( 'dismiss' ); |
| 941 | 857 | |
| 942 | - const renameButton = footerButton( { text: __( 'Rename style', 'formidable' ), buttonType: 'primary' } ); | |
| 858 | + const renameButton = footerButton({ text: __( 'Rename style', 'formidable' ), buttonType: 'primary' }); | |
| 943 | 859 | onClickPreventDefault( renameButton, () => renameStyle( styleId ) ); |
| 944 | 860 | |
| 945 | - return div( { | |
| 861 | + return div({ | |
| 946 | 862 | children: [ cancelButton, renameButton ] |
| 947 | - } ); | |
| 863 | + }); | |
| 948 | 864 | } |
| 949 | 865 | |
| 950 | 866 | /** |
| 951 | 867 | * Call frm_rename_style action when the rename style button is clicked in rename modal. |
| 952 | 868 | * |
| 953 | - * @param {string} styleId | |
| 954 | - * @return {void} | |
| 869 | + * @param {String} styleId | |
| 870 | + * @returns {void} | |
| 955 | 871 | */ |
| 956 | 872 | function renameStyle( styleId ) { |
| 957 | 873 | const styleNameInput = document.getElementById( 'frm_rename_style_name_input' ); |
| 958 | - const newStyleName = styleNameInput.value; | |
| 874 | + const newStyleName = styleNameInput.value; | |
| 959 | 875 | |
| 960 | 876 | if ( '' === newStyleName ) { |
| 961 | 877 | // Avoid setting an empty name. |
| 962 | 878 | // The button gets disabled on an input event when the name is empty. |
| @@ -962,27 +878,9 @@ | ||
| 962 | 878 | // The button gets disabled on an input event when the name is empty. |
| 963 | 879 | return; |
| 964 | 880 | } |
| 965 | 881 | |
| 966 | - if ( ! styleId || '0' === String( styleId ) ) { | |
| 967 | - // A new or duplicated style has no ID yet, so there is nothing to rename on the server. | |
| 968 | - // Update the post_title input (which overrides $_GET['style_name'] on save) and the | |
| 969 | - // visible style name instead of calling the rename_style endpoint. | |
| 970 | - const postTitleInput = document.querySelector( 'input[name="frm_style_setting[post_title]"]' ); | |
| 971 | - if ( postTitleInput ) { | |
| 972 | - postTitleInput.value = newStyleName; | |
| 973 | - } | |
| 974 | - | |
| 975 | - const styleNameElement = document.getElementById( 'frm_style_name' ); | |
| 976 | - if ( styleNameElement ) { | |
| 977 | - styleNameElement.textContent = newStyleName; | |
| 978 | - } | |
| 979 | - | |
| 980 | - success( __( 'Style has been renamed successfully', 'formidable' ) ); | |
| 981 | - return; | |
| 982 | - } | |
| 983 | - | |
| 984 | - const formData = new FormData(); | |
| 882 | + const formData = new FormData(); | |
| 985 | 883 | formData.append( 'style_id', styleId ); |
| 986 | 884 | formData.append( 'style_name', newStyleName ); |
| 987 | 885 | doJsonPost( 'rename_style', formData ).then( |
| 988 | 886 | /** |
| @@ -990,9 +888,9 @@ | ||
| 990 | 888 | * |
| 991 | 889 | * If on the list page, update the style card after renaming a style. |
| 992 | 890 | * On the edit page, update the style name element instead. |
| 993 | 891 | * |
| 994 | - * @return {void} | |
| 892 | + * @returns {void} | |
| 995 | 893 | */ |
| 996 | 894 | () => { |
| 997 | 895 | success( __( 'Style has been renamed successfully', 'formidable' ) ); |
| 998 | 896 | |
| @@ -1007,24 +905,33 @@ | ||
| 1007 | 905 | ); |
| 1008 | 906 | } |
| 1009 | 907 | |
| 1010 | 908 | /** |
| 1011 | - * @param {string} styleId | |
| 1012 | - * @param {string} newStyleName | |
| 1013 | - * @return {void} | |
| 909 | + * @param {String} styleId | |
| 910 | + * @param {String} newStyleName | |
| 911 | + * @returns {void} | |
| 1014 | 912 | */ |
| 1015 | 913 | function updateStyleNameInCard( styleId, newStyleName ) { |
| 1016 | - const card = getCardByStyleId( styleId ); | |
| 914 | + const card = getCardByStyleId( styleId ); | |
| 1017 | 915 | const titleElement = card.querySelector( '.frm-style-card-title' ); |
| 1018 | 916 | titleElement.textContent = newStyleName; |
| 1019 | 917 | } |
| 1020 | 918 | |
| 1021 | 919 | /** |
| 1022 | - * @param {string} styleId | |
| 1023 | - * @return {HTMLElement} The card element. | |
| 920 | + * @param {String} templateKey | |
| 921 | + * @returns {HTMLElement} | |
| 1024 | 922 | */ |
| 923 | + function getTemplateCard( templateKey ) { | |
| 924 | + const templateCard = document.getElementById( 'frm_template_style_cards_wrapper' ).querySelector( '.frm-style-card[data-template-key="' + templateKey + '"]' ); | |
| 925 | + return templateCard; | |
| 926 | + } | |
| 927 | + | |
| 928 | + /** | |
| 929 | + * @param {String} styleId | |
| 930 | + * @returns {HTMLElement} | |
| 931 | + */ | |
| 1025 | 932 | function getCardByStyleId( styleId ) { |
| 1026 | - const defaultCard = document.querySelector( `#frm_default_style_cards_wrapper > div[data-style-id="${ styleId }"]` ); | |
| 933 | + const defaultCard = document.querySelector( '#frm_default_style_cards_wrapper > div[data-style-id="' + styleId + '"]' ); | |
| 1027 | 934 | if ( defaultCard ) { |
| 1028 | 935 | return defaultCard; |
| 1029 | 936 | } |
| 1030 | 937 | return Array.from( document.getElementById( 'frm_custom_style_cards_wrapper' ).children ).find( card => card.dataset.styleId === styleId ); |
| @@ -1031,19 +938,19 @@ | ||
| 1031 | 938 | } |
| 1032 | 939 | |
| 1033 | 940 | /** |
| 1034 | 941 | * @param {HTMLElement} option |
| 1035 | - * @param {string} iconId | |
| 1036 | - * @return {void} | |
| 942 | + * @param {String} iconId | |
| 943 | + * @returns {void} | |
| 1037 | 944 | */ |
| 1038 | 945 | function addIconToOption( option, iconId ) { |
| 1039 | - const icon = frmDom.svg( { href: `#${ iconId }` } ); | |
| 946 | + const icon = frmDom.svg({ href: '#' + iconId }); | |
| 1040 | 947 | option.insertBefore( icon, option.firstChild ); |
| 1041 | 948 | } |
| 1042 | 949 | |
| 1043 | 950 | /** |
| 1044 | - * @param {string} styleId | |
| 1045 | - * @return {void} | |
| 951 | + * @param {String} styleId | |
| 952 | + * @returns {void} | |
| 1046 | 953 | */ |
| 1047 | 954 | function confirmResetStyle( styleId ) { |
| 1048 | 955 | stylerModal( |
| 1049 | 956 | 'frm_reset_style_modal', |
| @@ -1055,9 +962,9 @@ | ||
| 1055 | 962 | ); |
| 1056 | 963 | } |
| 1057 | 964 | |
| 1058 | 965 | /** |
| 1059 | - * @return {HTMLElement} The modal content element. | |
| 966 | + * @returns {HTMLElement} | |
| 1060 | 967 | */ |
| 1061 | 968 | function getResetStyleModalContent() { |
| 1062 | 969 | const content = div( __( 'Reset this style back to the default?', 'formidable' ) ); |
| 1063 | 970 | content.style.padding = '20px'; |
| @@ -1064,23 +971,23 @@ | ||
| 1064 | 971 | return content; |
| 1065 | 972 | } |
| 1066 | 973 | |
| 1067 | 974 | /** |
| 1068 | - * @param {string} styleId | |
| 1069 | - * @return {HTMLElement} The modal footer element. | |
| 975 | + * @param {String} styleId | |
| 976 | + * @returns {HTMLElement} | |
| 1070 | 977 | */ |
| 1071 | 978 | function getResetStyleModalFooter( styleId ) { |
| 1072 | - const cancelButton = footerButton( { | |
| 979 | + const cancelButton = footerButton({ | |
| 1073 | 980 | text: __( 'Cancel', 'formidable' ), |
| 1074 | 981 | buttonType: 'cancel' |
| 1075 | - } ); | |
| 982 | + }); | |
| 1076 | 983 | cancelButton.classList.add( 'dismiss' ); |
| 1077 | - const resetButton = footerButton( { | |
| 984 | + const resetButton = footerButton({ | |
| 1078 | 985 | text: __( 'Reset style', 'formidable' ), |
| 1079 | 986 | buttonType: 'primary' |
| 1080 | - } ); | |
| 987 | + }); | |
| 1081 | 988 | onClickPreventDefault( resetButton, () => resetStyle( styleId ) ); |
| 1082 | - return div( { children: [ cancelButton, resetButton ] } ); | |
| 989 | + return div({ children: [ cancelButton, resetButton ] }); | |
| 1083 | 990 | } |
| 1084 | 991 | |
| 1085 | 992 | /** |
| 1086 | 993 | * Handle reset dropdown action. |
| @@ -1085,10 +992,10 @@ | ||
| 1085 | 992 | /** |
| 1086 | 993 | * Handle reset dropdown action. |
| 1087 | 994 | * This function handles the front end routing for the reset action as reset works differently for edit and list views. |
| 1088 | 995 | * |
| 1089 | - * @param {string} styleId | |
| 1090 | - * @return {void} | |
| 996 | + * @param {String} styleId | |
| 997 | + * @returns {void} | |
| 1091 | 998 | */ |
| 1092 | 999 | function resetStyle( styleId ) { |
| 1093 | 1000 | if ( isListPage ) { |
| 1094 | 1001 | resetStyleOnListPage( styleId ); |
| @@ -1099,10 +1006,10 @@ | ||
| 1099 | 1006 | |
| 1100 | 1007 | /** |
| 1101 | 1008 | * Make a POST request to reset the style then reload the CSS and reset the card styles. |
| 1102 | 1009 | * |
| 1103 | - * @param {string} styleId | |
| 1104 | - * @return {void} | |
| 1010 | + * @param {String} styleId | |
| 1011 | + * @returns {void} | |
| 1105 | 1012 | */ |
| 1106 | 1013 | function resetStyleOnListPage( styleId ) { |
| 1107 | 1014 | const formData = new FormData(); |
| 1108 | 1015 | formData.append( 'style_id', styleId ); |
| @@ -1125,12 +1032,12 @@ | ||
| 1125 | 1032 | |
| 1126 | 1033 | /** |
| 1127 | 1034 | * Reset the style in-page (without actually updating it). |
| 1128 | 1035 | * |
| 1129 | - * @return {void} | |
| 1036 | + * @returns {void} | |
| 1130 | 1037 | */ |
| 1131 | 1038 | function resetStyleOnEditPage() { |
| 1132 | - jQuery.ajax( { | |
| 1039 | + jQuery.ajax({ | |
| 1133 | 1040 | type: 'POST', |
| 1134 | 1041 | url: ajaxurl, |
| 1135 | 1042 | data: { |
| 1136 | 1043 | action: 'frm_settings_reset', |
| @@ -1136,9 +1043,9 @@ | ||
| 1136 | 1043 | action: 'frm_settings_reset', |
| 1137 | 1044 | nonce: frmGlobal.nonce |
| 1138 | 1045 | }, |
| 1139 | 1046 | success: syncEditPageAfterResetAction |
| 1140 | - } ); | |
| 1047 | + }); | |
| 1141 | 1048 | } |
| 1142 | 1049 | |
| 1143 | 1050 | /** |
| 1144 | 1051 | * Handle reset success on edit page. |
| @@ -1146,9 +1053,9 @@ | ||
| 1146 | 1053 | * |
| 1147 | 1054 | * @todo Stop triggering change events with jQuery. And remove the other jQuery as well. |
| 1148 | 1055 | * |
| 1149 | 1056 | * @param {Object} response |
| 1150 | - * @return {void} | |
| 1057 | + * @returns {void} | |
| 1151 | 1058 | */ |
| 1152 | 1059 | function syncEditPageAfterResetAction( response ) { |
| 1153 | 1060 | let defaultValues = response.replace( /^\s+|\s+$/g, '' ); |
| 1154 | 1061 | if ( defaultValues.indexOf( '{' ) === 0 ) { |
| @@ -1155,9 +1062,9 @@ | ||
| 1155 | 1062 | defaultValues = JSON.parse( defaultValues ); |
| 1156 | 1063 | } |
| 1157 | 1064 | |
| 1158 | 1065 | for ( const key in defaultValues ) { |
| 1159 | - let targetInput = document.querySelector( `input[name$="[${ key }]"], select[name$="[${ key }]"]` ); | |
| 1066 | + let targetInput = document.querySelector( 'input[name$="[' + key + ']"], select[name$="[' + key + ']"]' ); | |
| 1160 | 1067 | if ( ! targetInput ) { |
| 1161 | 1068 | continue; |
| 1162 | 1069 | } |
| 1163 | 1070 | |
| @@ -1162,9 +1069,9 @@ | ||
| 1162 | 1069 | } |
| 1163 | 1070 | |
| 1164 | 1071 | if ( 'radio' === targetInput.getAttribute( 'type' ) ) { |
| 1165 | 1072 | // Reset the repeater icon dropdown. |
| 1166 | - targetInput = document.querySelector( `input[name$="[${ key }]"][value="${ defaultValues[ key ] }"]` ); | |
| 1073 | + targetInput = document.querySelector( 'input[name$="[' + key + ']"][value="' + defaultValues[ key ] + '"]' ); | |
| 1167 | 1074 | if ( targetInput ) { |
| 1168 | 1075 | targetInput.checked = true; |
| 1169 | 1076 | jQuery( targetInput ).trigger( 'change' ); |
| 1170 | 1077 | } |
| @@ -1178,9 +1085,8 @@ | ||
| 1178 | 1085 | jQuery( targetInput ).trigger( 'change' ); |
| 1179 | 1086 | } |
| 1180 | 1087 | } |
| 1181 | 1088 | |
| 1182 | - resetCustomCSSEditor(); | |
| 1183 | 1089 | jQuery( '#frm_submit_style, #frm_auto_width' ).prop( 'checked', false ); |
| 1184 | 1090 | jQuery( document.getElementById( 'frm_fieldset' ) ).trigger( 'change' ); |
| 1185 | 1091 | showStyleResetSuccessMessage(); |
| 1186 | 1092 | } |
| @@ -1185,26 +1091,11 @@ | ||
| 1185 | 1091 | showStyleResetSuccessMessage(); |
| 1186 | 1092 | } |
| 1187 | 1093 | |
| 1188 | 1094 | /** |
| 1189 | - * Reset the custom CSS editor. | |
| 1190 | - * | |
| 1191 | - * @return {void} | |
| 1192 | - */ | |
| 1193 | - function resetCustomCSSEditor() { | |
| 1194 | - const checkbox = document.getElementById( 'frm_enable_single_style_custom_css' ); | |
| 1195 | - const editorWrapper = document.getElementById( 'frm_single_style_custom_css_editor' ); | |
| 1196 | - if ( ! checkbox || ! editorWrapper ) { | |
| 1197 | - return; | |
| 1198 | - } | |
| 1199 | - checkbox.checked = false; | |
| 1200 | - editorWrapper.classList.add( 'frm_hidden' ); | |
| 1201 | - } | |
| 1202 | - | |
| 1203 | - /** | |
| 1204 | 1095 | * Reload Formidable CSS after a style is reset so the preview updates immediately without needing to reload the page. |
| 1205 | 1096 | * |
| 1206 | - * @return {void} | |
| 1097 | + * @returns {void} | |
| 1207 | 1098 | */ |
| 1208 | 1099 | function reloadCSSAfterStyleReset() { |
| 1209 | 1100 | const style = document.getElementById( 'frm-custom-theme-css' ); |
| 1210 | 1101 | if ( ! style ) { |
| @@ -1211,27 +1102,27 @@ | ||
| 1211 | 1102 | return; |
| 1212 | 1103 | } |
| 1213 | 1104 | |
| 1214 | 1105 | const newStyle = document.createElement( 'link' ); |
| 1215 | - newStyle.rel = 'stylesheet'; | |
| 1216 | - newStyle.type = 'text/css'; | |
| 1217 | - newStyle.href = `${ style.href }&key=${ getAutoId() }`; // Make the URL unique so the old stylesheet doesn't get picked up by cache. | |
| 1106 | + newStyle.rel = 'stylesheet'; | |
| 1107 | + newStyle.type = 'text/css'; | |
| 1108 | + newStyle.href = style.href + '&key=' + getAutoId(); // Make the URL unique so the old stylesheet doesn't get picked up by cache. | |
| 1218 | 1109 | |
| 1219 | 1110 | // Listen for the new style to load before removing the old style to avoid having no styles while the new style is loading. |
| 1220 | 1111 | newStyle.addEventListener( |
| 1221 | 1112 | 'load', |
| 1222 | 1113 | () => { |
| 1223 | - style.remove(); | |
| 1114 | + style.parentNode.removeChild( style ); | |
| 1224 | 1115 | newStyle.id = 'frm-custom-theme-css'; // Assign the old ID to the new style so it can be removed in the next reset action. |
| 1225 | 1116 | } |
| 1226 | 1117 | ); |
| 1227 | 1118 | |
| 1228 | - const head = document.getElementsByTagName( 'HEAD' )[ 0 ]; | |
| 1229 | - head.append( newStyle ); | |
| 1119 | + const head = document.getElementsByTagName( 'HEAD' )[0]; | |
| 1120 | + head.appendChild( newStyle ); | |
| 1230 | 1121 | } |
| 1231 | 1122 | |
| 1232 | 1123 | /** |
| 1233 | - * @return {number} The auto ID. | |
| 1124 | + * @returns {Number} | |
| 1234 | 1125 | */ |
| 1235 | 1126 | function getAutoId() { |
| 1236 | 1127 | return ++state.autoId; |
| 1237 | 1128 | } |
| @@ -1236,29 +1127,30 @@ | ||
| 1236 | 1127 | return ++state.autoId; |
| 1237 | 1128 | } |
| 1238 | 1129 | |
| 1239 | 1130 | /** |
| 1240 | - * @param {Object} data | |
| 1241 | - * @param {HTMLElement} data.anchor | |
| 1242 | - * @param {string} data.type | |
| 1243 | - * @return {HTMLElement} The dropdown item element. | |
| 1131 | + * @param {Object} data { | |
| 1132 | + * @type {Element} anchor | |
| 1133 | + * @type {String} type | |
| 1134 | + * } | |
| 1135 | + * @returns {Element} | |
| 1244 | 1136 | */ |
| 1245 | - function wrapDropdownItem( { anchor, type } ) { | |
| 1246 | - return div( { | |
| 1247 | - className: `dropdown-item frm-${ type }-style`, | |
| 1137 | + function wrapDropdownItem({ anchor, type }) { | |
| 1138 | + return div({ | |
| 1139 | + className: 'dropdown-item frm-' + type + '-style', | |
| 1248 | 1140 | child: anchor |
| 1249 | - } ); | |
| 1141 | + }); | |
| 1250 | 1142 | } |
| 1251 | 1143 | |
| 1252 | 1144 | /** |
| 1253 | 1145 | * This gets triggered through a hook called in frmAdminBuild.styleInit() from formidable_admin.js. |
| 1254 | 1146 | * |
| 1255 | - * @return {void} | |
| 1147 | + * @returns {void} | |
| 1256 | 1148 | */ |
| 1257 | 1149 | function initEditPage() { |
| 1258 | - const { debounce } = frmDom.util; | |
| 1150 | + const { debounce } = frmDom.util; | |
| 1259 | 1151 | const debouncedPreviewUpdate = debounce( () => changeStyling(), 100 ); |
| 1260 | - const debouncedColorChange = debounce( ( event, value ) => { | |
| 1152 | + const debouncedColorChange = debounce(( event, value ) => { | |
| 1261 | 1153 | /** |
| 1262 | 1154 | * Fires on style colorpicker change. |
| 1263 | 1155 | * |
| 1264 | 1156 | * @param {Event} data.event The color change event. |
| @@ -1269,94 +1161,37 @@ | ||
| 1269 | 1161 | |
| 1270 | 1162 | const debouncedTextSquishCheck = debounce( textSquishCheck, 300 ); |
| 1271 | 1163 | initPosClass(); // It's important that this gets called before we add event listeners because it triggers change events. |
| 1272 | 1164 | |
| 1273 | - [ 'frm_field_height', 'frm_field_font_size', 'frm_field_pad' ].forEach( selector => { | |
| 1165 | + ['frm_field_height', 'frm_field_font_size', 'frm_field_pad'].forEach( selector => { | |
| 1274 | 1166 | document.getElementById( selector ).addEventListener( 'change', debouncedTextSquishCheck ); |
| 1275 | - } ); | |
| 1167 | + }); | |
| 1276 | 1168 | |
| 1277 | - function detectColorFormat( value ) { | |
| 1278 | - if ( value.startsWith( 'rgba' ) ) { | |
| 1279 | - return 'rgba'; | |
| 1280 | - } | |
| 1281 | - if ( value.startsWith( 'rgb' ) ) { | |
| 1282 | - return 'rgb'; | |
| 1283 | - } | |
| 1284 | - if ( value.startsWith( 'hsla' ) ) { | |
| 1285 | - return 'hsla'; | |
| 1286 | - } | |
| 1287 | - if ( value.startsWith( 'hsl' ) ) { | |
| 1288 | - return 'hsl'; | |
| 1289 | - } | |
| 1290 | - return 'hex'; | |
| 1291 | - } | |
| 1292 | - | |
| 1293 | - const nativeInputValueDescriptor = Object.getOwnPropertyDescriptor( HTMLInputElement.prototype, 'value' ); | |
| 1294 | - | |
| 1295 | - jQuery( 'input.hex' ).each( function() { | |
| 1296 | - this.dataset.colorFormat = detectColorFormat( this.value ); | |
| 1297 | - | |
| 1298 | - // Prevent iris from overwriting non-hex formats with hex during color picking. | |
| 1299 | - const input = this; | |
| 1300 | - Object.defineProperty( input, 'value', { | |
| 1301 | - get() { | |
| 1302 | - return nativeInputValueDescriptor.get.call( this ); | |
| 1303 | - }, | |
| 1304 | - set( val ) { | |
| 1305 | - const format = input.dataset.colorFormat; | |
| 1306 | - if ( format && 'hex' !== format && /^#[0-9a-f]{3,8}$/i.test( val ) ) { | |
| 1307 | - return; | |
| 1308 | - } | |
| 1309 | - nativeInputValueDescriptor.set.call( this, val ); | |
| 1310 | - }, | |
| 1311 | - configurable: true | |
| 1312 | - } ); | |
| 1313 | - } ).on( 'keyup', function() { | |
| 1314 | - const newFormat = detectColorFormat( this.value ); | |
| 1315 | - if ( this.dataset.colorFormat !== newFormat ) { | |
| 1316 | - this.dataset.colorFormat = newFormat; | |
| 1317 | - const container = this.closest( '.wp-picker-container' ); | |
| 1318 | - if ( container ) { | |
| 1319 | - container.querySelector( '.wp-color-result-text' ).textContent = this.value; | |
| 1320 | - } | |
| 1321 | - debouncedColorChange( { target: this }, this.value ); | |
| 1322 | - } | |
| 1323 | - } ).wpColorPicker( { | |
| 1324 | - change( event, ui ) { | |
| 1325 | - const input = event.target; | |
| 1326 | - const format = input.dataset.colorFormat || 'hex'; | |
| 1327 | - let color; | |
| 1328 | - | |
| 1169 | + jQuery( 'input.hex' ).wpColorPicker({ | |
| 1170 | + change: function( event, ui ) { | |
| 1171 | + let color = jQuery( this ).wpColorPicker( 'color' ); | |
| 1329 | 1172 | trackUnsavedChange(); |
| 1330 | - | |
| 1331 | 1173 | if ( ui.color._alpha < 1 ) { |
| 1332 | - input.dataset.colorFormat = 'rgba'; | |
| 1174 | + // If there's transparency, use RGBA | |
| 1333 | 1175 | color = ui.color.toCSS( 'rgba' ); |
| 1334 | - } else if ( 'hex' === format ) { | |
| 1335 | - color = ui.color.toString(); | |
| 1336 | - } else { | |
| 1337 | - color = ui.color.toCSS( format ); | |
| 1338 | 1176 | } |
| 1339 | - | |
| 1340 | 1177 | debouncedColorChange( event, color ); |
| 1341 | 1178 | |
| 1342 | - input.value = color; | |
| 1343 | - | |
| 1344 | - if ( null !== input.getAttribute( 'data-alpha-color-type' ) ) { | |
| 1179 | + if ( null !== event.target.getAttribute( 'data-alpha-color-type' ) ) { | |
| 1345 | 1180 | debouncedPreviewUpdate(); |
| 1346 | 1181 | return; |
| 1347 | 1182 | } |
| 1348 | 1183 | |
| 1349 | - debouncedPreviewUpdate(); | |
| 1184 | + jQuery( event.target ).val( color ).trigger( 'change' ); | |
| 1350 | 1185 | } |
| 1351 | - } ); | |
| 1186 | + }); | |
| 1352 | 1187 | jQuery( '.wp-color-result-text' ).text( function( _, oldText ) { |
| 1353 | 1188 | const container = jQuery( this ).closest( '.wp-picker-container' ); |
| 1354 | - if ( container !== undefined && container[ 0 ].parentElement.classList.contains( 'frm-colorpicker' ) ) { | |
| 1355 | - return container[ 0 ].querySelector( '.wp-color-picker' ).value; | |
| 1189 | + if ( 'undefined' !== typeof container && container[0].parentElement.classList.contains( 'frm-colorpicker' ) ) { | |
| 1190 | + return container[0].querySelector( '.wp-color-picker' ).value; | |
| 1356 | 1191 | } |
| 1357 | 1192 | return oldText === 'Select Color' ? 'Select' : oldText; |
| 1358 | - } ); | |
| 1193 | + }); | |
| 1359 | 1194 | jQuery( '#frm_styling_form .styling_settings, #frm_styling_form .frm-field-shape, #frm_styling_form input[name="frm_style_setting[post_content][base_font_size]"]' ).on( 'change', debouncedPreviewUpdate ); |
| 1360 | 1195 | |
| 1361 | 1196 | // This is really only necessary for Pro. But if Pro is not up to date to initialize the datepicker in the sample form, it should still work because it's initialized here. |
| 1362 | 1197 | initDatepickerSample(); |
| @@ -1370,17 +1205,17 @@ | ||
| 1370 | 1205 | /** |
| 1371 | 1206 | * Sends an AJAX POST request for new CSS to use for the preview. |
| 1372 | 1207 | * This is called whenever a style setting is changed, generally using debouncedPreviewUpdate to avoid simultaneous requests. |
| 1373 | 1208 | * |
| 1374 | - * @return {void} | |
| 1209 | + * @returns {void} | |
| 1375 | 1210 | */ |
| 1376 | 1211 | function changeStyling() { |
| 1377 | 1212 | const styleInputs = Array.from( document.getElementById( 'frm_style_sidebar' ).querySelectorAll( 'input, select, textarea' ) ).filter( |
| 1378 | 1213 | input => 'style_name' === input.name || 0 === input.name.indexOf( 'frm_style_setting[post_content]' ) |
| 1379 | 1214 | ); |
| 1380 | - const locStr = JSON.stringify( jQuery( styleInputs ).serializeArray() ); | |
| 1215 | + const locStr = JSON.stringify( jQuery( styleInputs ).serializeArray() ); | |
| 1381 | 1216 | |
| 1382 | - jQuery.ajax( { | |
| 1217 | + jQuery.ajax({ | |
| 1383 | 1218 | type: 'POST', |
| 1384 | 1219 | url: ajaxurl, |
| 1385 | 1220 | data: { |
| 1386 | 1221 | action: 'frm_change_styling', |
| @@ -1386,24 +1221,24 @@ | ||
| 1386 | 1221 | action: 'frm_change_styling', |
| 1387 | 1222 | nonce: frmGlobal.nonce, |
| 1388 | 1223 | frm_style_setting: locStr |
| 1389 | 1224 | }, |
| 1390 | - success: css => { | |
| 1225 | + success: ( css ) => { | |
| 1391 | 1226 | handleChangeStylingSuccess( css ); |
| 1392 | 1227 | setSelectPlaceholderColor(); |
| 1393 | 1228 | } |
| 1394 | - } ); | |
| 1229 | + }); | |
| 1395 | 1230 | } |
| 1396 | 1231 | |
| 1397 | 1232 | /** |
| 1398 | 1233 | * Update the CSS used for the preview on the edit page when a styling input has been updated. |
| 1399 | 1234 | * |
| 1400 | - * @param {string} css The response from the frm_change_styling request. | |
| 1401 | - * @return {void} | |
| 1235 | + * @param {String} css The response from the frm_change_styling request. | |
| 1236 | + * @returns {void} | |
| 1402 | 1237 | */ |
| 1403 | 1238 | function handleChangeStylingSuccess( css ) { |
| 1404 | 1239 | // Validate the string response. A valid output will include rules with .with_frm_style |
| 1405 | - if ( ! css.includes( '.with_frm_style' ) ) { | |
| 1240 | + if ( -1 === css.indexOf( '.with_frm_style' ) ) { | |
| 1406 | 1241 | // Handle error (possibly a permission error, or an outdated nonce). |
| 1407 | 1242 | alert( css ); |
| 1408 | 1243 | return; |
| 1409 | 1244 | } |
| @@ -1413,17 +1248,17 @@ | ||
| 1413 | 1248 | /** |
| 1414 | 1249 | * Possibly pop up with a warning that "text will not display correctly if the field height is too small relative to the field padding and text size". |
| 1415 | 1250 | * This can be triggered when modifying font size, height, and padding. |
| 1416 | 1251 | * |
| 1417 | - * @return {void} | |
| 1252 | + * @returns {void} | |
| 1418 | 1253 | */ |
| 1419 | 1254 | function textSquishCheck() { |
| 1420 | 1255 | if ( null !== frmDom.util.getCookie( 'frm-style-text-squish-check' ) ) { |
| 1421 | 1256 | return; |
| 1422 | 1257 | } |
| 1423 | - const height = document.getElementById( 'frm_field_height' ).value.replace( /\D/g, '' ); | |
| 1258 | + const height = document.getElementById( 'frm_field_height' ).value.replace( /\D/g, '' ); | |
| 1424 | 1259 | const paddingEntered = document.getElementById( 'frm_field_pad' ).value.split( ' ' ); |
| 1425 | - const paddingCount = paddingEntered.length; | |
| 1260 | + const paddingCount = paddingEntered.length; | |
| 1426 | 1261 | |
| 1427 | 1262 | frmDom.util.setCookie( 'frm-style-text-squish-check', 1, 30 ); |
| 1428 | 1263 | |
| 1429 | 1264 | // If too many or too few padding entries, leave now |
| @@ -1432,12 +1267,12 @@ | ||
| 1432 | 1267 | } |
| 1433 | 1268 | |
| 1434 | 1269 | const size = document.getElementById( 'frm_field_font_size' ).value.replace( /\D/g, '' ); |
| 1435 | 1270 | // Get the top and bottom padding from entered values |
| 1436 | - const paddingTop = paddingEntered[ 0 ].replace( /\D/g, '' ); | |
| 1437 | - let paddingBottom = paddingTop; | |
| 1271 | + const paddingTop = paddingEntered[0].replace( /\D/g, '' ); | |
| 1272 | + let paddingBottom = paddingTop; | |
| 1438 | 1273 | if ( paddingCount >= 3 ) { |
| 1439 | - paddingBottom = paddingEntered[ 2 ].replace( /\D/g, '' ); | |
| 1274 | + paddingBottom = paddingEntered[2].replace( /\D/g, '' ); | |
| 1440 | 1275 | } |
| 1441 | 1276 | |
| 1442 | 1277 | // Check if there is enough space for text |
| 1443 | 1278 | const textSpace = height - size - paddingTop - paddingBottom - 3; |
| @@ -1449,16 +1284,16 @@ | ||
| 1449 | 1284 | /** |
| 1450 | 1285 | * When the Collapse icons are updated, sync the dropdown. |
| 1451 | 1286 | * Otherwise the previously selected value will still appear as the selected value. |
| 1452 | 1287 | * |
| 1453 | - * @return {void} | |
| 1288 | + * @returns {void} | |
| 1454 | 1289 | */ |
| 1455 | 1290 | jQuery( document ).on( 'change', '.frm-dropdown-menu input[type="radio"]', function() { |
| 1456 | 1291 | trackUnsavedChange(); |
| 1457 | 1292 | |
| 1458 | - const radio = this; | |
| 1293 | + const radio = this; | |
| 1459 | 1294 | const btnGrp = radio.closest( '.btn-group' ); |
| 1460 | - const btnId = btnGrp.getAttribute( 'id' ); | |
| 1295 | + const btnId = btnGrp.getAttribute( 'id' ); | |
| 1461 | 1296 | |
| 1462 | 1297 | const select = document.getElementById( btnId.replace( '_select', '' ) ); |
| 1463 | 1298 | if ( select ) { |
| 1464 | 1299 | select.value = radio.value; |
| @@ -1463,9 +1298,9 @@ | ||
| 1463 | 1298 | if ( select ) { |
| 1464 | 1299 | select.value = radio.value; |
| 1465 | 1300 | } |
| 1466 | 1301 | |
| 1467 | - jQuery( btnGrp ).children( 'button' ).html( `${ radio.nextElementSibling.innerHTML } <b class="caret"></b>` ); | |
| 1302 | + jQuery( btnGrp ).children( 'button' ).html( radio.nextElementSibling.innerHTML + ' <b class="caret"></b>' ); | |
| 1468 | 1303 | |
| 1469 | 1304 | const activeItem = btnGrp.querySelector( '.dropdown-item.active' ); |
| 1470 | 1305 | if ( activeItem ) { |
| 1471 | 1306 | activeItem.classList.remove( 'active' ); |
| @@ -1471,9 +1306,9 @@ | ||
| 1471 | 1306 | activeItem.classList.remove( 'active' ); |
| 1472 | 1307 | } |
| 1473 | 1308 | |
| 1474 | 1309 | radio.closest( '.dropdown-item' ).classList.add( 'active' ); |
| 1475 | - } ); | |
| 1310 | + }); | |
| 1476 | 1311 | |
| 1477 | 1312 | if ( frm_admin_js.requireAccordionTitleClickListener ) { |
| 1478 | 1313 | document.querySelectorAll( '.styling_settings h3.accordion-section-title' ).forEach( el => { |
| 1479 | 1314 | el.addEventListener( 'click', event => { |
| @@ -1479,17 +1314,33 @@ | ||
| 1479 | 1314 | el.addEventListener( 'click', event => { |
| 1480 | 1315 | if ( ! event.target.closest( 'button' ) ) { |
| 1481 | 1316 | el.querySelector( 'button' ).click(); |
| 1482 | 1317 | } |
| 1483 | - } ); | |
| 1484 | - } ); | |
| 1318 | + }); | |
| 1319 | + }); | |
| 1485 | 1320 | } |
| 1486 | 1321 | } |
| 1487 | 1322 | |
| 1488 | 1323 | /** |
| 1324 | + * @param {Event} event | |
| 1325 | + */ | |
| 1326 | + function maybeCollapseSettings( event ) { | |
| 1327 | + let expanded; | |
| 1328 | + const sectionParent = event.target.parentElement; | |
| 1329 | + if ( event.type === 'keydown' ) { | |
| 1330 | + expanded = sectionParent.classList.toggle( 'open' ); | |
| 1331 | + jQuery( sectionParent.querySelector( '.accordion-section-content' ) ).toggle( ! expanded ).slideToggle( 150 ); // Animate toggle as in click/enter. | |
| 1332 | + } else { | |
| 1333 | + expanded = sectionParent.classList.contains( 'open' ); | |
| 1334 | + } | |
| 1335 | + | |
| 1336 | + event.target.setAttribute( 'aria-expanded', expanded ); | |
| 1337 | + } | |
| 1338 | + | |
| 1339 | + /** | |
| 1489 | 1340 | * @param {HTMLElement} input |
| 1490 | 1341 | * @param {HTMLElement} container |
| 1491 | - * @return {void} | |
| 1342 | + * @returns {void} | |
| 1492 | 1343 | */ |
| 1493 | 1344 | function checkFloatingLabelsForStyles( input, container ) { |
| 1494 | 1345 | if ( ! container ) { |
| 1495 | 1346 | container = input.closest( '.frm_inside_container' ); |
| @@ -1509,16 +1360,18 @@ | ||
| 1509 | 1360 | if ( firstOpt.hasAttribute( 'data-label' ) ) { |
| 1510 | 1361 | firstOpt.textContent = firstOpt.getAttribute( 'data-label' ); |
| 1511 | 1362 | firstOpt.removeAttribute( 'data-label' ); |
| 1512 | 1363 | } |
| 1513 | - } else if ( firstOpt.textContent ) { | |
| 1514 | - firstOpt.setAttribute( 'data-label', firstOpt.textContent ); | |
| 1515 | - firstOpt.textContent = ''; | |
| 1364 | + } else { | |
| 1365 | + if ( firstOpt.textContent ) { | |
| 1366 | + firstOpt.setAttribute( 'data-label', firstOpt.textContent ); | |
| 1367 | + firstOpt.textContent = ''; | |
| 1368 | + } | |
| 1516 | 1369 | } |
| 1517 | 1370 | } |
| 1518 | 1371 | |
| 1519 | 1372 | /** |
| 1520 | - * @return {void} | |
| 1373 | + * @returns {void} | |
| 1521 | 1374 | */ |
| 1522 | 1375 | function initPosClass() { |
| 1523 | 1376 | const positionSetting = document.getElementById( 'frm_position' ); |
| 1524 | 1377 | |
| @@ -1532,13 +1385,13 @@ | ||
| 1532 | 1385 | |
| 1533 | 1386 | /** |
| 1534 | 1387 | * Update label container classes when the label "Position" setting is changed. |
| 1535 | 1388 | * |
| 1536 | - * @return {void} | |
| 1389 | + * @returns {void} | |
| 1537 | 1390 | */ |
| 1538 | 1391 | function setPosClass() { |
| 1539 | 1392 | /*jshint validthis:true */ |
| 1540 | - let { value } = this; | |
| 1393 | + let value = this.value; | |
| 1541 | 1394 | if ( value === 'none' ) { |
| 1542 | 1395 | value = 'top'; |
| 1543 | 1396 | } else if ( value === 'no_label' ) { |
| 1544 | 1397 | value = 'none'; |
| @@ -1544,23 +1397,23 @@ | ||
| 1544 | 1397 | value = 'none'; |
| 1545 | 1398 | } |
| 1546 | 1399 | |
| 1547 | 1400 | document.getElementById( 'frm_style_preview' ).querySelectorAll( '.frm_form_field.frm-default-label-position, #frm_sample_form .frm_form_field' ).forEach( container => { |
| 1548 | - const input = container.querySelector( ':scope > input, :scope > select, :scope > textarea' ); // Fields that support floating label should have a directly child input/textarea/select. | |
| 1401 | + const input = container.querySelector( ':scope > input, :scope > select, :scope > textarea' ); // Fields that support floating label should have a directly child input/textarea/select. | |
| 1549 | 1402 | 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. |
| 1550 | - const currentValue = shouldForceTopStyling ? 'top' : value; | |
| 1403 | + const currentValue = shouldForceTopStyling ? 'top' : value; | |
| 1551 | 1404 | |
| 1552 | 1405 | container.classList.remove( 'frm_top_container', 'frm_left_container', 'frm_right_container', 'frm_none_container', 'frm_inside_container' ); |
| 1553 | - container.classList.add( `frm_${ currentValue }_container` ); | |
| 1406 | + container.classList.add( 'frm_' + currentValue + '_container' ); | |
| 1554 | 1407 | |
| 1555 | 1408 | if ( 'inside' === currentValue ) { |
| 1556 | 1409 | checkFloatingLabelsForStyles( input, container ); |
| 1557 | 1410 | } |
| 1558 | - } ); | |
| 1411 | + }); | |
| 1559 | 1412 | } |
| 1560 | 1413 | |
| 1561 | 1414 | /** |
| 1562 | - * @return {void} | |
| 1415 | + * @returns {void} | |
| 1563 | 1416 | */ |
| 1564 | 1417 | function initFloatingLabels() { |
| 1565 | 1418 | [ 'focus', 'blur', 'change' ].forEach( |
| 1566 | 1419 | eventName => frmDom.util.documentOn( |
| @@ -1576,12 +1429,12 @@ | ||
| 1576 | 1429 | * The signature add on expects that validateFormSubmit is callable. |
| 1577 | 1430 | * Without this, drawing in a signature field triggers a "Uncaught ReferenceError: frmFrontForm is not defined" error. |
| 1578 | 1431 | * We don't want the validation to actually triggr, so just fill in an empty function. |
| 1579 | 1432 | * |
| 1580 | - * @return {void} | |
| 1433 | + * @returns {void} | |
| 1581 | 1434 | */ |
| 1582 | 1435 | function fillMissingSignatureValidationFunction() { |
| 1583 | - if ( window.__FRMSIG === undefined || window.frmFrontForm !== undefined ) { | |
| 1436 | + if ( 'undefined' === typeof window.__FRMSIG || 'undefined' !== typeof window.frmFrontForm ) { | |
| 1584 | 1437 | return; |
| 1585 | 1438 | } |
| 1586 | 1439 | |
| 1587 | 1440 | window.frmFrontForm = { validateFormSubmit: () => {} }; |
| @@ -1589,19 +1442,14 @@ | ||
| 1589 | 1442 | |
| 1590 | 1443 | /** |
| 1591 | 1444 | * Enable the datepicker in the sample form preview. |
| 1592 | 1445 | * |
| 1593 | - * @return {void} | |
| 1446 | + * @returns {void} | |
| 1594 | 1447 | */ |
| 1595 | 1448 | function initDatepickerSample() { |
| 1596 | - // If flatpickr is defined, then is a recent version of Pro which handles the datepicker preview as it's a PRO feature. | |
| 1597 | - if ( 'undefined' !== typeof flatpickr ) { | |
| 1598 | - return; | |
| 1599 | - } | |
| 1600 | - | |
| 1601 | 1449 | const $sample = jQuery( '#datepicker_sample' ); |
| 1602 | 1450 | if ( $sample.length && 'function' === typeof $sample.datepicker ) { |
| 1603 | - $sample.datepicker( { changeMonth: true, changeYear: true } ); | |
| 1451 | + $sample.datepicker({ changeMonth: true, changeYear: true }); | |
| 1604 | 1452 | } |
| 1605 | 1453 | } |
| 1606 | 1454 | |
| 1607 | 1455 | /** |
| @@ -1619,10 +1467,10 @@ | ||
| 1619 | 1467 | return; |
| 1620 | 1468 | } |
| 1621 | 1469 | |
| 1622 | 1470 | // Function to change the color of a select element |
| 1623 | - const changeSelectColor = select => { | |
| 1624 | - if ( select.options[ select.selectedIndex ]?.classList.contains( 'frm-select-placeholder' ) ) { | |
| 1471 | + const changeSelectColor = ( select ) => { | |
| 1472 | + if ( select.options[select.selectedIndex] && select.options[select.selectedIndex].classList.contains( 'frm-select-placeholder' ) ) { | |
| 1625 | 1473 | select.style.setProperty( 'color', textColorDisabled, 'important' ); |
| 1626 | 1474 | } else { |
| 1627 | 1475 | select.style.color = ''; |
| 1628 | 1476 | } |
| @@ -1628,15 +1476,15 @@ | ||
| 1628 | 1476 | } |
| 1629 | 1477 | }; |
| 1630 | 1478 | |
| 1631 | 1479 | // Use a loop to iterate through each select element |
| 1632 | - selects.forEach( select => { | |
| 1480 | + selects.forEach( ( select ) => { | |
| 1633 | 1481 | // Apply the color change to each select element |
| 1634 | 1482 | changeSelectColor( select ); |
| 1635 | 1483 | |
| 1636 | 1484 | // Add an event listener for future changes |
| 1637 | 1485 | select.addEventListener( 'change', () => changeSelectColor( select ) ); |
| 1638 | - } ); | |
| 1486 | + }); | |
| 1639 | 1487 | } |
| 1640 | 1488 | |
| 1641 | 1489 | // Hook into the styleInit function in formidable_admin.js |
| 1642 | 1490 | wp.hooks.addAction( 'frm_style_editor_init', 'formidable', initEditPage ); |