HEX
Server: LiteSpeed
System: Linux server315.web-hosting.com 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: globfdxw (6114)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: /home/globfdxw/www/wp-content/plugins/wpforms-pdf/assets/js/modules/notifications.js
/* global wpf, WPForms, wpforms_builder */

/**
 * @param wpforms_builder.pdf.settings.notifications_no_choices
 * @param wpforms_builder.pdf.settings.notifications_no_results
 * @param choicesInstance.setChoiceByValue
 */

// noinspection JSUnusedGlobalSymbols, JSUnusedLocalSymbols

/**
 * WPForms PDF: Notifications module.
 *
 * @since 1.0.0
 *
 * @param {Object} document Document object.
 * @param {Object} window   Window object.
 * @param {jQuery} $        jQuery object.
 *
 * @return {Object} Public functions and properties.
 */
export default function( document, window, $ ) { // eslint-disable-line no-unused-vars, max-lines-per-function
	/**
	 * Elements holder.
	 *
	 * @since 1.0.0
	 *
	 * @type {Object}
	 */
	const el = {};

	/**
	 * Public functions and properties.
	 *
	 * @since 1.0.0
	 */
	const app = {

		/**
		 * Start the engine.
		 *
		 * @since 1.0.0
		 */
		init() {
			app.ready();
		},

		/**
		 * Start the engine.
		 *
		 * @since 1.0.0
		 */
		ready() {
			app.setup();
			app.bindEvents();
			app.initExistingNotificationDropdowns();
		},

		/**
		 * Setup. Prepare some variables.
		 *
		 * @since 1.0.0
		 */
		setup() {
			// Cache DOM elements.
			el.$builder = $( '#wpforms-builder' );

			app.notifications = app.getAllNotifications();
		},

		/**
		 * Bind events.
		 *
		 * @since 1.0.0
		 */
		bindEvents() {
			el.$builder
				.on( 'wpformsPanelSectionSwitch', app.panelSectionSwitch )
				.on( 'wpformsPanelSwitch', app.panelSwitch )
				.on( 'wpformsSettingsBlockAdded', app.pdfAdded )
				.on( 'wpformsSettingsBlockCloned', app.pdfCloned )
				.on( 'wpformsUndoRedoRun', app.undoRedoRun )
				.on( 'change', '.wpforms-pdf-notifications select', function() {
					app.changeNotificationsValue( $( this ) );
				} );
		},

		/**
		 * The PDF block was added.
		 *
		 * @since 1.0.0
		 *
		 * @param {Event}  e      The event object.
		 * @param {jQuery} $block The block element.
		 */
		pdfAdded( e, $block ) {
			if ( $block.data( 'block-type' ) !== 'pdf' ) {
				return;
			}

			WPForms.Admin.Builder.UndoRedo?.preventRecord( true );
			app.initNotificationDropdownsForBlock( $block );
			app.refreshNotificationDropdown( $block.find( '.wpforms-pdf-notifications select' ) );
			app.setDefaultValue( $block );
			WPForms.Admin.Builder.UndoRedo?.preventRecord( 'continue' );
		},

		/**
		 * The PDF block was added.
		 *
		 * @since 1.0.0
		 *
		 * @param {Event}  e           The event object.
		 * @param {jQuery} $block      The block element.
		 * @param {string} clonedPdfId The cloned PDF block ID.
		 */
		pdfCloned( e, $block, clonedPdfId ) {
			if ( $block.data( 'block-type' ) !== 'pdf' ) {
				return;
			}

			WPForms.Admin.Builder.UndoRedo?.preventRecord( true );
			app.initNotificationDropdownsForClonedBlock( $block, clonedPdfId );
			WPForms.Admin.Builder.UndoRedo?.preventRecord( 'continue' );
		},

		/**
		 * The undo/redo action was run.
		 *
		 * @since 1.2.0
		 *
		 * @param {Event}  e           The event object.
		 * @param {string} commandType The command type.
		 * @param {Object} command     The command object.
		 */
		undoRedoRun( e, commandType, command ) {
			if ( ! app.shouldProcessUndoRedoEvent( command.args?.event ?? '' ) ) {
				return;
			}

			app.initExistingNotificationDropdowns();
		},

		/**
		 * Whether the undo/redo event should be processed.
		 *
		 * @since 1.2.0
		 *
		 * @param {string} event Event name.
		 *
		 * @return {boolean} True when the event should be processed.
		 */
		shouldProcessUndoRedoEvent( event ) {
			const events = [
				'wpformsSettingsBlockCloned',
				'wpformsSettingsBlockAdded',
				'wpformsSettingsBlockDeleted',
			];

			return events.includes( event );
		},

		/**
		 * Initialize existing notification dropdowns for all elements on the page.
		 *
		 * @since 1.0.0
		 */
		initExistingNotificationDropdowns() {
			// Return if Choices.js is not available.
			if ( typeof window.Choices !== 'function' ) {
				return;
			}

			// Initialize existing notification dropdowns
			el.$builder.find( '.wpforms-pdf-notifications select' ).each( function() {
				app.initializeChoicesForSelect( $( this ) );
			} );
		},

		/**
		 * Initialize notification dropdown for a specific block.
		 *
		 * @since 1.0.0
		 *
		 * @param {jQuery} $block The block element.
		 */
		initNotificationDropdownsForBlock( $block ) {
			// Return if Choices.js is not available.
			if ( typeof window.Choices !== 'function' ) {
				return;
			}

			// Initialize notification dropdowns this block.
			const $select = $block.find( '.wpforms-pdf-notifications select' );

			app.initializeChoicesForSelect( $select );
		},

		/**
		 * Re-initialize notification dropdown for a cloned block.
		 *
		 * @since 1.0.0
		 *
		 * @param {jQuery} $block      The block element.
		 * @param {string} clonedPdfId The cloned PDF block ID.
		 */
		initNotificationDropdownsForClonedBlock( $block, clonedPdfId ) {
			const pdfId = $block.data( 'block-id' );
			const $originSelect = $( `#wpforms-panel-field-pdfs-${ clonedPdfId }-notifications` );
			const originValue = $originSelect.last().data( 'choicesjs' )?.getValue();

			// language=HTML
			const $newSelect = $( '<select multiple></select>' )
				.attr( 'id', `wpforms-panel-field-pdfs-${ pdfId }-notifications` )
				.attr( 'name', `settings[pdfs][${ pdfId }][notifications]` );

			let selectedValues = originValue ? wpf.listPluck( originValue, 'value' ) : $originSelect.val();

			selectedValues = Array.isArray( selectedValues ) ? selectedValues : [ selectedValues ];

			app.notifications.forEach( function( item ) {
				// language=HTML
				const $option = $( '<option></option>' )
					.val( item.id )
					.prop( 'selected', selectedValues.includes( item.id ) )
					.text( item.name );

				$newSelect.append( $option );
			} );

			// Remove existing choices.
			const $choices = $block.find( '.wpforms-pdf-notifications .choices' );

			$choices.after( $newSelect );
			$choices.remove();

			app.initNotificationDropdownsForBlock( $block );
		},

		/**
		 * Initialize Choices.js for a select element.
		 *
		 * @since 1.0.0
		 *
		 * @param {jQuery} $select The select element.
		 */
		initializeChoicesForSelect( $select ) {
			// Initialize Choices.js if not already initialized.
			if ( $select.data( 'choicesjs' ) ) {
				return;
			}

			app.notifications = app.getAllNotifications();

			WPForms.Admin.Builder.WPFormsChoicesJS.setup(
				$select[ 0 ],
				{
					removeItemButton: true,
					noChoicesText: wpforms_builder.pdf.settings.notifications_no_choices,
					noResultsText: wpforms_builder.pdf.settings.notifications_no_results,
				},
				{}
			);

			// Save the form state after initialization if it's the initial save.
			if ( wpf && wpf.initialSave === true ) {
				wpf._updateFormState();
			}
		},

		/**
		 * Set the default Notification.
		 *
		 * @since 1.0.0
		 *
		 * @param {jQuery} $block The block element.
		 */
		setDefaultValue( $block ) {
			const $select = $block.find( '.wpforms-pdf-notifications select' );
			const choicesInstance = $select.data( 'choicesjs' );

			// Skip if no Choices.js instance found.
			if ( ! choicesInstance ) {
				return;
			}

			// By default, we should use the first available Notification.
			const defaultValue = app.notifications[ 0 ]?.id ?? '1';

			choicesInstance.setChoiceByValue( defaultValue );
			app.changeNotificationsValue( $select );
		},

		/**
		 * Change notifications value.
		 *
		 * @since 1.0.0
		 *
		 * @param {jQuery} $select The select element.
		 */
		changeNotificationsValue( $select ) {
			// Return if no select element provided.
			if ( ! $select.length ) {
				return;
			}

			// Find the JSON field associated with this select.
			const $jsonField = $select.closest( '.wpforms-builder-settings-block-content' )
				.find( '.wpforms-panel-field-pdf-notifications-json' );

			// Update the JSON field value if found.
			if ( $jsonField.length ) {
				$jsonField.val( JSON.stringify( $select.val() ) );
			}
		},

		/**
		 * Handle panel switch event.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event     Event object.
		 * @param {string} panelName Name of the panel.
		 */
		panelSwitch( event, panelName ) {
			// Check if switching to the settings panel.
			if ( panelName === 'settings' ) {
				const section = $( '#wpforms-panel-settings .wpforms-panel-sidebar' )
					.find( '.wpforms-panel-sidebar-section.active' )
					.data( 'section' );

				// If the PDF section is active, refresh all PDF notification dropdowns.
				if ( section === 'pdf' ) {
					app.refreshAllPDFNotificationDropdowns();
				}
			}
		},

		/**
		 * Handle panel section switch event.
		 *
		 * @since 1.0.0
		 *
		 * @param {Object} event       Event object.
		 * @param {string} sectionName Name of the section.
		 */
		panelSectionSwitch( event, sectionName ) {
			// If switching to the PDF section, refresh all PDF notification dropdowns.
			if ( sectionName === 'pdf' ) {
				app.refreshAllPDFNotificationDropdowns();
			}
		},

		/**
		 * Refresh PDF notification dropdown.
		 *
		 * @since 1.0.0
		 *
		 * @param {jQuery} $select The select element.
		 */
		refreshNotificationDropdown( $select ) {
			const choicesInstance = $select.data( 'choicesjs' );

			// Skip if no Choices.js instance found.
			if ( ! choicesInstance ) {
				return;
			}

			// Get current selected values.
			const currentValues = choicesInstance.getValue();
			const selectedValues = currentValues?.map( ( item ) => item.value ) ?? [];

			// Format notifications for Choices.js.
			const choicesData = app.notifications.map( ( notification ) => ( {
				value: notification.id,
				label: notification.name,
			} ) );

			// Clear and reset choices.
			choicesInstance.clearStore();
			choicesInstance.setChoices( choicesData, 'value', 'label', true );

			// Restore previously selected values if they still exist.
			for ( let i = 0; i < selectedValues.length; i++ ) {
				if ( app.notifications.some( ( notification ) => notification.id === selectedValues[ i ] ) ) {
					choicesInstance.setChoiceByValue( selectedValues[ i ] );
				}
			}

			// Update the JSON field.
			app.changeNotificationsValue( $select );
		},

		/**
		 * Refresh all PDF notification dropdowns.
		 *
		 * @since 1.0.0
		 */
		refreshAllPDFNotificationDropdowns() {
			// Get all notifications from the form.
			app.notifications = app.getAllNotifications();

			// Refresh each PDF notification dropdown.
			$( '.wpforms-pdf-notifications select' ).each( function() {
				app.refreshNotificationDropdown( $( this ) );
			} );
		},

		/**
		 * Get all notifications from the form.
		 *
		 * @since 1.0.0
		 *
		 * @return {Array} Array of notification objects.
		 */
		getAllNotifications() {
			const notifications = [];

			// Get all notification blocks.
			$( '.wpforms-panel-content-section-notifications .wpforms-notification' ).each( function() {
				const $notification = $( this );
				const id = $notification.data( 'block-id' ).toString();
				const name = $notification.find( '.wpforms-builder-settings-block-name' ).text().trim();

				// Add to a notification array if both ID and name are present.
				if ( id && name ) {
					notifications.push( {
						id,
						name,
					} );
				}
			} );

			return notifications;
		},
	};

	// Return the public-facing methods.
	return app;
}