// Setup search functionality function setupSearch() { const searchInput = document.getElementById('channel-search'); let searchTimeout; // Search input handler searchInput.addEventListener('input', function() { const query = this.value.trim(); clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { if (query.length >= 2) { searchChannels(query); } else if (query.length === 0) { selectCategory(currentCategory); } }, 300); }); // Keyboard shortcut support (Ctrl+K) document.addEventListener('keydown', function(e) { if ((e.ctrlKey || e.metaKey) && e.key === 'k') { e.preventDefault(); searchInput.focus(); searchInput.select(); } // Escape to clear search if (e.key === 'Escape' && document.activeElement === searchInput) { searchInput.value = ''; selectCategory(currentCategory); searchInput.blur(); } }); // Search on Enter searchInput.addEventListener('keydown', function(e) { if (e.key === 'Enter') { const query = this.value.trim(); if (query.length >= 2) { searchChannels(query); } } }); } // Search channels function searchChannels(query) { if (!allChannelsData.channels) { console.warn('No channel data available for search'); return; } const filteredChannels = allChannelsData.channels.filter(channel => channel.name.toLowerCase().includes(query.toLowerCase()) || channel.categoryName.toLowerCase().includes(query.toLowerCase()) || (channel.number && channel.number.toString().includes(query)) ); // Reset page to 1 for search results currentPage = 1; document.getElementById('section-title').textContent = `Search Results for "${query}"`; document.getElementById('section-description').textContent = `${filteredChannels.length} channels found`; document.getElementById('category-filter-info').textContent = `Searching all categories`; displayChannels(filteredChannels); } // Filter channels by type (for filter buttons) function filterChannels(filterType) { // Update filter buttons document.querySelectorAll('.filter-btn').forEach(btn => { btn.className = btn.className.replace('active bg-blue-600 text-white', 'bg-gray-200 text-gray-700'); }); event.target.className = event.target.className.replace('bg-gray-200 text-gray-700', 'active bg-blue-600 text-white'); // Apply filter switch(filterType) { case 'all': selectCategory('all'); break; case 'network-tv': selectCategory('network-tv'); break; case 'sports': selectCategory('sports-networks'); break; case 'international': selectCategory('canada'); break; } } // Display error message function displayError(message) { const container = document.getElementById('channels-container'); container.innerHTML = `

${message}

`; } event.stopPropagation(); } else { } // Save back to localStorage // Update the button const icon = btn.querySelector('i'); btn.classList.add('bg-red-50'); btn.classList.remove('bg-gray-50'); icon.classList.add('fas', 'fa-heart', 'text-red-500'); icon.classList.remove('far', 'fa-heart', 'text-gray-400'); } else { btn.classList.add('bg-gray-50'); btn.classList.remove('bg-red-50'); icon.classList.add('far', 'fa-heart', 'text-gray-400'); icon.classList.remove('fas', 'fa-heart', 'text-red-500'); } // Show feedback } // Refresh channel data async function refreshChannelData() { const refreshIcon = document.getElementById('refresh-icon'); if (refreshIcon) { refreshIcon.innerHTML = ''; } await channelSystem.loadExcelData(true); if (refreshIcon) { refreshIcon.innerHTML = ''; } showToast('Channel data refreshed successfully!', 'success'); updateStats(); } } if (exportDiv) { exportDiv.classList.remove('hidden'); } else { exportDiv.classList.add('hidden'); } } } // Update statistics function updateStats() { const stats = channelSystem.getChannelStats(); // Update total channels count const totalChannelsEl = document.getElementById('total-channels-count'); if (totalChannelsEl) { totalChannelsEl.textContent = stats.totalChannels.toLocaleString(); } // Update last updated time if we have a place for it console.log('Channel stats:', stats); } // Show toast notification function showToast(message, type = 'info') { const toast = document.createElement('div'); toast.className = `fixed top-4 right-4 z-50 px-6 py-3 rounded-lg shadow-lg text-white transform translate-x-full transition-transform duration-300 ${ type === 'success' ? 'bg-green-600' : type === 'error' ? 'bg-red-600' : 'bg-blue-600' }`; toast.innerHTML = `
${message}
`; document.body.appendChild(toast); // Animate in setTimeout(() => { toast.classList.remove('translate-x-full'); }, 100); // Animate out and remove setTimeout(() => { toast.classList.add('translate-x-full'); setTimeout(() => { document.body.removeChild(toast); }, 300); }, 3000); } // Enhanced select category to work with channel system function selectCategory(categoryId) { currentCategory = categoryId; // Update UI document.querySelectorAll('.category-item').forEach(item => { item.classList.remove('bg-blue-100', 'border-l-4', 'border-blue-600'); item.classList.add('hover:bg-gray-100'); }); const activeItem = document.querySelector(`[data-category-id="${categoryId}"]`); if (activeItem) { activeItem.classList.remove('hover:bg-gray-100'); activeItem.classList.add('bg-blue-100', 'border-l-4', 'border-blue-600'); } // Load channels from API for specific category if (categoryId === 'all') { document.getElementById('section-title').textContent = 'All Channels'; document.getElementById('section-description').textContent = `${allChannelsData.channels ? allChannelsData.channels.length : 0} channels in this category`; displayChannels(allChannelsData.channels ? allChannelsData.channels.slice(0, channelsPerPage) : []); } else { loadCategoryChannels(categoryId); } }