// CSP-Safe JavaScript - All inline event handlers moved here // This file handles all onclick, onchange, and other inline event handlers document.addEventListener('DOMContentLoaded', function() { initEventDelegation(); initToastNotifications(); initNfoModal(); initConfirmDialogs(); initSelectRedirects(); initLogoutForms(); initSeasonSwitcher(); initBinaryBlacklist(); initImageModal(); initTabSwitcher(); initPreviewModal(); initRegexManagement(); initMediainfoAndFilelist(); initCartFunctionality(); initAdminMenu(); initSidebarToggle(); initDropdownMenus(); initImageFallbacks(); initProfileTabs(); initAdminUserEdit(); initMobileEnhancements(); initAdminDashboardCharts(); initAdminGroups(); initTinyMCE(); initAdminSpecificFeatures(); // Initialize page-specific functionality from inline scripts initMyMovies(); initAuthPages(); initProfileEdit(); initDetailsPageImageModal(); initAddToCart(); initMoviesLayoutToggle(); }); // Event delegation for dynamically added elements function initEventDelegation() { document.addEventListener('click', function(e) { // Handle toast close buttons if (e.target.classList.contains('toast-close') || e.target.closest('.toast-close')) { const toast = e.target.closest('.toast-notification'); if (toast) { toast.remove(); } } // Handle NFO modal close if (e.target.hasAttribute('data-close-nfo-modal') || e.target.closest('[data-close-nfo-modal]')) { e.preventDefault(); closeNfoModal(); } // Handle NFO modal open if (e.target.hasAttribute('data-open-nfo') || e.target.closest('[data-open-nfo]')) { e.preventDefault(); const guid = e.target.getAttribute('data-open-nfo') || e.target.closest('[data-open-nfo]').getAttribute('data-open-nfo'); if (guid) { openNfoModal(guid); } } // Handle logout if (e.target.hasAttribute('data-logout') || e.target.closest('[data-logout]')) { e.preventDefault(); const logoutForm = document.getElementById('logout-form'); if (logoutForm) { logoutForm.submit(); } } // Handle confirm delete if (e.target.hasAttribute('data-confirm-delete') || e.target.closest('[data-confirm-delete]')) { const confirmed = confirm('Are you sure you want to delete this item?'); if (!confirmed) { e.preventDefault(); } } // Handle confirm action if (e.target.hasAttribute('data-confirm') || e.target.closest('[data-confirm]')) { const message = e.target.getAttribute('data-confirm') || e.target.closest('[data-confirm]').getAttribute('data-confirm'); const confirmed = confirm(message); if (!confirmed) { e.preventDefault(); } } // Handle download NZB buttons if (e.target.classList.contains('download-nzb') || e.target.closest('.download-nzb')) { if (typeof showToast === 'function') { showToast('Downloading NZB...', 'success'); } } // Handle season switcher if (e.target.hasAttribute('data-season') || e.target.closest('[data-season]')) { e.preventDefault(); const seasonNumber = e.target.getAttribute('data-season') || e.target.closest('[data-season]').getAttribute('data-season'); switchSeason(seasonNumber); } // Handle binary blacklist delete if (e.target.hasAttribute('data-delete-blacklist') || e.target.closest('[data-delete-blacklist]')) { const id = e.target.getAttribute('data-delete-blacklist') || e.target.closest('[data-delete-blacklist]').getAttribute('data-delete-blacklist'); const confirmed = confirm('Are you sure? This will delete the blacklist from this list.'); if (confirmed && typeof ajax_binaryblacklist_delete === 'function') { ajax_binaryblacklist_delete(id); } e.preventDefault(); } // Handle admin groups management actions const actionTarget = e.target.closest('[data-action]'); if (actionTarget) { const action = actionTarget.dataset.action; const groupId = actionTarget.dataset.groupId; const status = actionTarget.dataset.status; switch(action) { case 'show-reset-modal': showResetAllModal(); break; case 'hide-reset-modal': hideResetAllModal(); break; case 'show-purge-modal': showPurgeAllModal(); break; case 'hide-purge-modal': hidePurgeAllModal(); break; case 'toggle-group-status': ajax_group_status(groupId, status); break; case 'toggle-backfill': ajax_backfill_status(groupId, status); break; case 'reset-group': ajax_group_reset(groupId); break; case 'delete-group': confirmGroupDelete(groupId); break; case 'purge-group': confirmGroupPurge(groupId); break; case 'reset-all': ajax_group_reset_all(); break; case 'purge-all': ajax_group_purge_all(); break; } } }); // Handle select redirects document.addEventListener('change', function(e) { if (e.target.hasAttribute('data-redirect-on-change')) { const url = e.target.value; if (url && url !== '#') { window.location.href = url; } } }); } // Toast Notifications function initToastNotifications() { // showToast is defined globally for backward compatibility window.showToast = function(message, type) { type = type || 'success'; let container = document.getElementById('toast-container'); if (!container) { // Create container if it doesn't exist container = document.createElement('div'); container.id = 'toast-container'; container.className = 'fixed top-4 right-4 z-50'; document.body.appendChild(container); } const toast = document.createElement('div'); toast.className = 'toast-notification ' + type; const iconClass = type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-circle' : 'fa-info-circle'; toast.innerHTML = '' + '' + ''; container.appendChild(toast); // Auto-remove after 5 seconds setTimeout(function() { toast.classList.add('removing'); setTimeout(function() { toast.remove(); }, 300); }, 5000); }; } // NFO Modal function initNfoModal() { window.openNfoModal = function(guid) { const modal = document.getElementById('nfoModal'); const content = document.getElementById('nfoContent'); if (!modal || !content) return; // Show modal modal.classList.remove('hidden'); // Reset content with loading message content.innerHTML = '
${escapeHtml(message)}
Loading file list...
No files available
'; return; } let html = 'Total Files: ${data.total}
| File Name | Size |
|---|---|
| ${escapeHtml(fileName)} | ${fileSize} |
${escapeHtml(error.message)}
Loading media information...
No media information available
'; return; } let html = '${escapeHtml(data.subs)}
${escapeHtml(error.message)}