Add massive collection of CSS, JavaScript and theme assets that were previously excluded: **CSS Files (681 total):** - HVAC plugin-specific styles (hvac-*.css): 34 files including dashboard, certificates, registration, mobile nav, accessibility fixes, animations, and welcome popup - Theme framework files (Astra, builder systems, layouts): 200+ files - Plugin compatibility styles (WooCommerce, WPForms, Elementor, Contact Form 7): 150+ files - WordPress core and editor styles: 50+ files - Responsive and RTL language support: 200+ files **JavaScript Files (400+ total):** - HVAC plugin functionality (hvac-*.js): 27 files including menu systems, dashboard enhancements, profile sharing, mobile responsive features, accessibility, and animations - Framework and library files: jQuery plugins, GSAP, AOS, Swiper, Chart.js, Lottie, Isotope - Plugin compatibility scripts: WPForms, WooCommerce, Elementor, Contact Form 7, LifterLMS - WordPress core functionality: customizer, admin, block editor compatibility - Third-party integrations: Stripe, SMTP, analytics, search functionality **Assets:** - Certificate background images and logos - Comprehensive theme styling infrastructure - Mobile-responsive design systems - Cross-browser compatibility assets - Performance-optimized minified versions **Updated .gitignore:** - Fixed asset directory whitelisting patterns to properly include CSS/JS/images - Added proper directory structure recognition (!/assets/css/, !/assets/js/, etc.) - Maintains security by excluding sensitive files while including essential assets This commit provides the complete frontend infrastructure needed for: - Full theme functionality and styling - Plugin feature implementations - Mobile responsiveness and accessibility - Cross-browser compatibility - Performance optimization - Developer workflow support
		
			
				
	
	
		
			552 lines
		
	
	
		
			No EOL
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			552 lines
		
	
	
		
			No EOL
		
	
	
		
			22 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Certificate Actions JavaScript
 | |
|  * 
 | |
|  * Handles the AJAX interactions for certificate viewing, emailing, and revocation.
 | |
|  */
 | |
| 
 | |
| (function($) {
 | |
|     'use strict';
 | |
| 
 | |
|     // Certificate Actions
 | |
|     const CertificateActions = {
 | |
|         /**
 | |
|          * Initialize certificate actions
 | |
|          */
 | |
|         init: function() {
 | |
|             // View certificate
 | |
|             $(document).on('click', '.hvac-view-certificate', this.viewCertificate);
 | |
|             
 | |
|             // Email certificate
 | |
|             $(document).on('click', '.hvac-email-certificate', this.emailCertificate);
 | |
|             
 | |
|             // Revoke certificate
 | |
|             $(document).on('click', '.hvac-revoke-certificate', this.revokeCertificate);
 | |
|             
 | |
|             // Close certificate modal
 | |
|             $(document).on('click', '.hvac-modal-close, .hvac-modal-overlay', this.closeCertificateModal);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * View certificate
 | |
|          */
 | |
|         viewCertificate: function(e) {
 | |
|             e.preventDefault();
 | |
|             
 | |
|             const $button = $(this);
 | |
|             const certificateId = $button.data('certificate-id');
 | |
|             
 | |
|             // Disable button while processing
 | |
|             $button.prop('disabled', true).addClass('hvac-loading');
 | |
|             
 | |
|             // AJAX request
 | |
|             $.ajax({
 | |
|                 url: hvacCertificateData.ajaxUrl,
 | |
|                 type: 'POST',
 | |
|                 data: {
 | |
|                     action: 'hvac_get_certificate_url',
 | |
|                     certificate_id: certificateId,
 | |
|                     nonce: hvacCertificateData.viewNonce
 | |
|                 },
 | |
|                 success: function(response) {
 | |
|                     $button.prop('disabled', false).removeClass('hvac-loading');
 | |
|                     
 | |
|                     if (response.success && response.data.url) {
 | |
|                         // Show preview modal if it exists
 | |
|                         if ($('#hvac-certificate-modal').length > 0) {
 | |
|                             CertificateActions.showCertificateModal(response.data.url);
 | |
|                         } else {
 | |
|                             // Open in new tab
 | |
|                             window.open(response.data.url, '_blank');
 | |
|                         }
 | |
|                     } else {
 | |
|                         // Use toast notification instead of alert
 | |
|                         if (window.HVACToast) {
 | |
|                             HVACToast.error(response.data.message || 'Failed to get certificate URL');
 | |
|                         } else {
 | |
|                             alert(response.data.message || 'Error: Failed to get certificate URL');
 | |
|                         }
 | |
|                     }
 | |
|                 },
 | |
|                 error: function() {
 | |
|                     $button.prop('disabled', false).removeClass('hvac-loading');
 | |
|                     // Use toast notification instead of alert
 | |
|                     if (window.HVACToast) {
 | |
|                         HVACToast.error('Failed to connect to server');
 | |
|                     } else {
 | |
|                         alert('Error: Failed to connect to server');
 | |
|                     }
 | |
|                 }
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Show certificate modal
 | |
|          */
 | |
|         showCertificateModal: function(url) {
 | |
|             // Set iframe source
 | |
|             $('#hvac-certificate-preview').attr('src', url);
 | |
|             
 | |
|             // Show modal
 | |
|             $('.hvac-modal-overlay').fadeIn(200);
 | |
|             $('#hvac-certificate-modal').fadeIn(200);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Close certificate modal
 | |
|          */
 | |
|         closeCertificateModal: function(e) {
 | |
|             if (e.target === this || $(e.target).hasClass('hvac-modal-close')) {
 | |
|                 $('.hvac-modal-overlay').fadeOut(200);
 | |
|                 $('#hvac-certificate-modal').fadeOut(200);
 | |
|                 
 | |
|                 // Clear iframe src after fade
 | |
|                 setTimeout(function() {
 | |
|                     $('#hvac-certificate-preview').attr('src', '');
 | |
|                 }, 200);
 | |
|             }
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Email certificate
 | |
|          */
 | |
|         emailCertificate: function(e) {
 | |
|             e.preventDefault();
 | |
|             
 | |
|             const $button = $(this);
 | |
|             const certificateId = $button.data('certificate-id');
 | |
|             
 | |
|             // Confirm sending
 | |
|             if (!confirm('Send certificate to attendee via email?')) {
 | |
|                 return;
 | |
|             }
 | |
|             
 | |
|             // Disable button while processing
 | |
|             $button.prop('disabled', true).addClass('hvac-loading');
 | |
|             
 | |
|             // AJAX request
 | |
|             $.ajax({
 | |
|                 url: hvacCertificateData.ajaxUrl,
 | |
|                 type: 'POST',
 | |
|                 data: {
 | |
|                     action: 'hvac_email_certificate',
 | |
|                     certificate_id: certificateId,
 | |
|                     nonce: hvacCertificateData.emailNonce
 | |
|                 },
 | |
|                 success: function(response) {
 | |
|                     $button.prop('disabled', false).removeClass('hvac-loading');
 | |
|                     
 | |
|                     if (response.success) {
 | |
|                         // Use toast notification instead of alert
 | |
|                         if (window.HVACToast) {
 | |
|                             HVACToast.success(response.data.message || 'Certificate sent successfully');
 | |
|                         } else {
 | |
|                             alert(response.data.message || 'Certificate sent successfully');
 | |
|                         }
 | |
|                         
 | |
|                         // Update UI to indicate certificate has been emailed
 | |
|                         const $row = $button.closest('tr');
 | |
|                         $row.find('.hvac-certificate-emailed').text('Yes');
 | |
|                     } else {
 | |
|                         // Use toast notification instead of alert
 | |
|                         if (window.HVACToast) {
 | |
|                             HVACToast.error(response.data.message || 'Failed to send certificate');
 | |
|                         } else {
 | |
|                             alert(response.data.message || 'Error: Failed to send certificate');
 | |
|                         }
 | |
|                     }
 | |
|                 },
 | |
|                 error: function() {
 | |
|                     $button.prop('disabled', false).removeClass('hvac-loading');
 | |
|                     // Use toast notification instead of alert
 | |
|                     if (window.HVACToast) {
 | |
|                         HVACToast.error('Failed to connect to server');
 | |
|                     } else {
 | |
|                         alert('Error: Failed to connect to server');
 | |
|                     }
 | |
|                 }
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Revoke certificate
 | |
|          */
 | |
|         revokeCertificate: function(e) {
 | |
|             e.preventDefault();
 | |
|             
 | |
|             const $button = $(this);
 | |
|             const certificateId = $button.data('certificate-id');
 | |
|             
 | |
|             // Prompt for revocation reason
 | |
|             const reason = prompt('Please enter a reason for revoking this certificate:', '');
 | |
|             
 | |
|             // If canceled
 | |
|             if (reason === null) {
 | |
|                 return;
 | |
|             }
 | |
|             
 | |
|             // Disable button while processing
 | |
|             $button.prop('disabled', true).addClass('hvac-loading');
 | |
|             
 | |
|             // AJAX request
 | |
|             $.ajax({
 | |
|                 url: hvacCertificateData.ajaxUrl,
 | |
|                 type: 'POST',
 | |
|                 data: {
 | |
|                     action: 'hvac_revoke_certificate',
 | |
|                     certificate_id: certificateId,
 | |
|                     reason: reason,
 | |
|                     nonce: hvacCertificateData.revokeNonce
 | |
|                 },
 | |
|                 success: function(response) {
 | |
|                     $button.prop('disabled', false).removeClass('hvac-loading');
 | |
|                     
 | |
|                     if (response.success) {
 | |
|                         // Use toast notification instead of alert
 | |
|                         if (window.HVACToast) {
 | |
|                             HVACToast.success(response.data.message || 'Certificate revoked successfully');
 | |
|                         } else {
 | |
|                             alert(response.data.message || 'Certificate revoked successfully');
 | |
|                         }
 | |
|                         
 | |
|                         // Update UI to indicate certificate has been revoked
 | |
|                         const $row = $button.closest('tr');
 | |
|                         $row.find('.hvac-certificate-status').text('Revoked');
 | |
|                         $row.find('.hvac-certificate-status').addClass('hvac-status-revoked');
 | |
|                         $row.find('.hvac-certificate-revoked-date').text(response.data.revoked_date || 'Today');
 | |
|                         
 | |
|                         // Hide revoke button, show unrevoke button if it exists
 | |
|                         $button.hide();
 | |
|                         $row.find('.hvac-unrevoke-certificate').show();
 | |
|                     } else {
 | |
|                         // Use toast notification instead of alert
 | |
|                         if (window.HVACToast) {
 | |
|                             HVACToast.error(response.data.message || 'Failed to revoke certificate');
 | |
|                         } else {
 | |
|                             alert(response.data.message || 'Error: Failed to revoke certificate');
 | |
|                         }
 | |
|                     }
 | |
|                 },
 | |
|                 error: function() {
 | |
|                     $button.prop('disabled', false).removeClass('hvac-loading');
 | |
|                     // Use toast notification instead of alert
 | |
|                     if (window.HVACToast) {
 | |
|                         HVACToast.error('Failed to connect to server');
 | |
|                     } else {
 | |
|                         alert('Error: Failed to connect to server');
 | |
|                     }
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     // Generate Certificates AJAX functionality
 | |
|     const GenerateCertificates = {
 | |
|         /**
 | |
|          * Initialize generate certificates functionality
 | |
|          */
 | |
|         init: function() {
 | |
|             // Event selection
 | |
|             $(document).on('change', '#event_id', this.loadAttendees);
 | |
|             
 | |
|             // Certificate generation (use event delegation for dynamic form)
 | |
|             $(document).on('submit', '#generate-certificates-form', this.generateCertificates);
 | |
|             
 | |
|             // Helper buttons (use event delegation for dynamic buttons)
 | |
|             $(document).on('click', '#select-all-attendees', this.selectAllAttendees);
 | |
|             $(document).on('click', '#select-checked-in', this.selectCheckedInAttendees);
 | |
|             $(document).on('click', '#deselect-all-attendees', this.deselectAllAttendees);
 | |
|             
 | |
|             // Certificate preview (use event delegation for dynamic buttons)
 | |
|             $(document).on('click', '.hvac-preview-certificate', this.showCertificatePreview);
 | |
|             $(document).on('click', '.hvac-modal-close', this.closeCertificatePreview);
 | |
|             $(document).on('click', '#hvac-certificate-preview-modal', function(e) {
 | |
|                 if (e.target === this) {
 | |
|                     GenerateCertificates.closeCertificatePreview(e);
 | |
|                 }
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Load attendees via AJAX when event is selected
 | |
|          */
 | |
|         loadAttendees: function(e) {
 | |
|             const eventId = $(this).val();
 | |
|             
 | |
|             if (!eventId) {
 | |
|                 $('#step-select-attendees').hide();
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             // Show loading
 | |
|             $('#attendees-loading').show();
 | |
|             $('#attendees-content').hide();
 | |
| 
 | |
|             $.ajax({
 | |
|                 url: hvacCertificateData.ajaxUrl,
 | |
|                 type: 'POST',
 | |
|                 data: {
 | |
|                     action: 'hvac_get_event_attendees',
 | |
|                     event_id: eventId,
 | |
|                     nonce: hvacCertificateData.generateNonce
 | |
|                 },
 | |
|                 success: function(response) {
 | |
|                     if (response.success) {
 | |
|                         GenerateCertificates.renderAttendees(response.data.attendees, response.data.event_title);
 | |
|                         $('#step-select-attendees').show();
 | |
|                     } else {
 | |
|                         // Use toast notification instead of alert
 | |
|                         if (window.HVACToast) {
 | |
|                             HVACToast.error(response.data.message);
 | |
|                         } else {
 | |
|                             alert('Error: ' + response.data.message);
 | |
|                         }
 | |
|                     }
 | |
|                 },
 | |
|                 error: function() {
 | |
|                     // Use toast notification instead of alert
 | |
|                     if (window.HVACToast) {
 | |
|                         HVACToast.error('Failed to load attendees. Please try again.');
 | |
|                     } else {
 | |
|                         alert('Failed to load attendees. Please try again.');
 | |
|                     }
 | |
|                 },
 | |
|                 complete: function() {
 | |
|                     $('#attendees-loading').hide();
 | |
|                     $('#attendees-content').show();
 | |
|                 }
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Render attendees table
 | |
|          */
 | |
|         renderAttendees: function(attendees, eventTitle) {
 | |
|             if (attendees.length === 0) {
 | |
|                 $('#attendees-table-container').html('<p class="hvac-empty-state">This event has no attendees.</p>');
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             let tableHtml = `
 | |
|                 <div class="hvac-form-group">
 | |
|                     <div class="hvac-table-actions">
 | |
|                         <button type="button" class="hvac-button hvac-secondary" id="select-all-attendees">Select All</button>
 | |
|                         <button type="button" class="hvac-button hvac-secondary" id="select-checked-in">Select Checked-In Only</button>
 | |
|                         <button type="button" class="hvac-button hvac-secondary" id="deselect-all-attendees">Deselect All</button>
 | |
|                     </div>
 | |
|                     
 | |
|                     <div class="hvac-attendees-table-wrapper">
 | |
|                         <table class="hvac-attendees-table">
 | |
|                             <thead>
 | |
|                                 <tr>
 | |
|                                     <th class="hvac-checkbox-column">
 | |
|                                         <input type="checkbox" id="select-all-checkbox">
 | |
|                                     </th>
 | |
|                                     <th>Attendee</th>
 | |
|                                     <th>Email</th>
 | |
|                                     <th>Status</th>
 | |
|                                     <th>Certificate</th>
 | |
|                                 </tr>
 | |
|                             </thead>
 | |
|                             <tbody>
 | |
|             `;
 | |
| 
 | |
|             attendees.forEach(function(attendee) {
 | |
|                 const checkedInClass = attendee.check_in ? 'hvac-checked-in' : '';
 | |
|                 const statusClass = attendee.check_in ? 'hvac-status-checked-in' : 'hvac-status-not-checked-in';
 | |
|                 const statusText = attendee.check_in ? 'Checked In' : 'Not Checked In';
 | |
|                 const certificateStatus = attendee.has_certificate ? 'Certificate Issued' : 'No Certificate';
 | |
|                 const hasCertClass = attendee.has_certificate ? 'hvac-has-certificate' : '';
 | |
|                 
 | |
|                 tableHtml += `
 | |
|                     <tr class="${hasCertClass} ${checkedInClass}">
 | |
|                         <td>
 | |
|                             ${!attendee.has_certificate ? 
 | |
|                                 `<input type="checkbox" name="attendee_ids[]" value="${attendee.attendee_id}" class="attendee-checkbox" ${attendee.check_in ? 'checked' : ''}>` : 
 | |
|                                 ''
 | |
|                             }
 | |
|                         </td>
 | |
|                         <td>${attendee.holder_name}</td>
 | |
|                         <td>${attendee.holder_email}</td>
 | |
|                         <td><span class="${statusClass}">${statusText}</span></td>
 | |
|                         <td>${certificateStatus}</td>
 | |
|                     </tr>
 | |
|                 `;
 | |
|             });
 | |
| 
 | |
|             tableHtml += `
 | |
|                             </tbody>
 | |
|                         </table>
 | |
|                     </div>
 | |
|                 </div>
 | |
|             `;
 | |
| 
 | |
|             $('#attendees-table-container').html(tableHtml);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Generate certificates via AJAX
 | |
|          */
 | |
|         generateCertificates: function(e) {
 | |
|             e.preventDefault();
 | |
|             
 | |
|             const $form = $(this);
 | |
|             const formData = $form.serialize();
 | |
|             
 | |
|             // Show loading
 | |
|             const $submitBtn = $form.find('button[type="submit"]');
 | |
|             $submitBtn.prop('disabled', true).text('Generating...');
 | |
|             
 | |
|             // Hide previous messages
 | |
|             $('.hvac-success-message, .hvac-errors').remove();
 | |
| 
 | |
|             $.ajax({
 | |
|                 url: hvacCertificateData.ajaxUrl,
 | |
|                 type: 'POST',
 | |
|                 data: formData + '&action=hvac_generate_certificates&nonce=' + hvacCertificateData.generateNonce,
 | |
|                 success: function(response) {
 | |
|                     if (response.success) {
 | |
|                         // Show success message with preview option
 | |
|                         let successMessage = `
 | |
|                             <div class="hvac-success-message">
 | |
|                                 <p>${response.data.message}</p>
 | |
|                                 <p><a href="/certificate-reports/" class="hvac-button hvac-primary">View All Certificates</a></p>
 | |
|                         `;
 | |
|                         
 | |
|                         // Add preview buttons if certificates were generated
 | |
|                         if (response.data.preview_urls && response.data.preview_urls.length > 0) {
 | |
|                             successMessage += '<div class="hvac-certificate-previews"><h4>Preview Generated Certificates:</h4>';
 | |
|                             response.data.preview_urls.forEach(function(preview) {
 | |
|                                 successMessage += `
 | |
|                                     <button type="button" class="hvac-button hvac-secondary hvac-preview-certificate" 
 | |
|                                             data-url="${preview.preview_url}" 
 | |
|                                             data-attendee="${preview.attendee_name}">
 | |
|                                         Preview - ${preview.attendee_name}
 | |
|                                     </button>
 | |
|                                 `;
 | |
|                             });
 | |
|                             successMessage += '</div>';
 | |
|                         }
 | |
|                         
 | |
|                         successMessage += '</div>';
 | |
|                         $form.before(successMessage);
 | |
|                         
 | |
|                         // Reload attendees to update certificate status
 | |
|                         $('#event_id').trigger('change');
 | |
|                     } else {
 | |
|                         // Show error message
 | |
|                         $form.before(`
 | |
|                             <div class="hvac-errors">
 | |
|                                 <p class="hvac-error">${response.data.message}</p>
 | |
|                             </div>
 | |
|                         `);
 | |
|                     }
 | |
|                 },
 | |
|                 error: function() {
 | |
|                     $form.before(`
 | |
|                         <div class="hvac-errors">
 | |
|                             <p class="hvac-error">Failed to generate certificates. Please try again.</p>
 | |
|                         </div>
 | |
|                     `);
 | |
|                 },
 | |
|                 complete: function() {
 | |
|                     $submitBtn.prop('disabled', false).text('Generate Certificates');
 | |
|                 }
 | |
|             });
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Select all attendees
 | |
|          */
 | |
|         selectAllAttendees: function(e) {
 | |
|             e.preventDefault();
 | |
|             $('.attendee-checkbox').prop('checked', true);
 | |
|             $('#select-all-checkbox').prop('checked', true);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Select only checked-in attendees
 | |
|          */
 | |
|         selectCheckedInAttendees: function(e) {
 | |
|             e.preventDefault();
 | |
|             $('.attendee-checkbox').each(function() {
 | |
|                 const $row = $(this).closest('tr');
 | |
|                 $(this).prop('checked', $row.hasClass('hvac-checked-in'));
 | |
|             });
 | |
|             $('#select-all-checkbox').prop('checked', false);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Deselect all attendees
 | |
|          */
 | |
|         deselectAllAttendees: function(e) {
 | |
|             e.preventDefault();
 | |
|             $('.attendee-checkbox').prop('checked', false);
 | |
|             $('#select-all-checkbox').prop('checked', false);
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Show certificate preview modal
 | |
|          */
 | |
|         showCertificatePreview: function(e) {
 | |
|             e.preventDefault();
 | |
|             const $button = $(this);
 | |
|             const url = $button.data('url');
 | |
|             const attendeeName = $button.data('attendee');
 | |
|             
 | |
|             if (!url) {
 | |
|                 // Use toast notification instead of alert
 | |
|                 if (window.HVACToast) {
 | |
|                     HVACToast.error('Preview URL not available');
 | |
|                 } else {
 | |
|                     alert('Preview URL not available');
 | |
|                 }
 | |
|                 return;
 | |
|             }
 | |
|             
 | |
|             // Create modal if it doesn't exist
 | |
|             if ($('#hvac-certificate-preview-modal').length === 0) {
 | |
|                 $('body').append(`
 | |
|                     <div id="hvac-certificate-preview-modal" class="hvac-modal">
 | |
|                         <div class="hvac-modal-content">
 | |
|                             <div class="hvac-modal-header">
 | |
|                                 <h3>Certificate Preview</h3>
 | |
|                                 <span class="hvac-modal-close">×</span>
 | |
|                             </div>
 | |
|                             <div class="hvac-modal-body">
 | |
|                                 <iframe id="hvac-certificate-preview-iframe" src="" width="100%" height="600px" frameborder="0"></iframe>
 | |
|                             </div>
 | |
|                         </div>
 | |
|                     </div>
 | |
|                 `);
 | |
|             }
 | |
|             
 | |
|             // Update modal title and iframe source
 | |
|             $('#hvac-certificate-preview-modal h3').text(`Certificate Preview - ${attendeeName}`);
 | |
|             $('#hvac-certificate-preview-iframe').attr('src', url);
 | |
|             
 | |
|             // Show modal
 | |
|             $('#hvac-certificate-preview-modal').show();
 | |
|         },
 | |
| 
 | |
|         /**
 | |
|          * Close certificate preview modal
 | |
|          */
 | |
|         closeCertificatePreview: function(e) {
 | |
|             e.preventDefault();
 | |
|             $('#hvac-certificate-preview-modal').hide();
 | |
|             $('#hvac-certificate-preview-iframe').attr('src', '');
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     // Initialize when document is ready
 | |
|     $(document).ready(function() {
 | |
|         CertificateActions.init();
 | |
|         
 | |
|         // Always initialize Generate Certificates functionality if on the generate certificates page
 | |
|         // (the form may not exist initially but will be created dynamically)
 | |
|         if ($('#event_id').length || $('#generate-certificates-form').length) {
 | |
|             GenerateCertificates.init();
 | |
|         }
 | |
|     });
 | |
| 
 | |
| })(jQuery); |