/** * Search Modal Functionality */ import { api } from './api.js'; // Search state let searchTimeout = null; const SEARCH_DEBOUNCE_MS = 300; // Elements const searchModal = document.getElementById('searchModal'); const searchBackdrop = document.getElementById('searchBackdrop'); const searchInput = document.getElementById('searchInput'); const closeSearch = document.getElementById('closeSearch'); const searchLoading = document.getElementById('searchLoading'); const searchGrid = document.getElementById('searchGrid'); // Search button in sidebar const searchNavButton = document.querySelector('[data-view="search"]'); /** * Open search modal */ function openSearchModal() { searchModal.classList.add('active'); setTimeout(() => searchInput.focus(), 100); } /** * Close search modal */ function closeSearchModal() { searchModal.classList.remove('active'); searchInput.value = ''; searchGrid.innerHTML = ''; searchLoading.style.display = 'none'; } /** * Perform search */ async function performSearch(query) { if (!query || query.trim().length < 2) { searchGrid.innerHTML = ''; searchLoading.style.display = 'none'; return; } // Show loading searchLoading.style.display = 'flex'; try { // Search in the API const response = await api.searchRophim(query); searchLoading.style.display = 'none'; if (response && response.movies && response.movies.length > 0) { // Display results searchGrid.innerHTML = response.movies.map(movie => { return `
${movie.title}

${movie.title}

${movie.year || ''} ${movie.quality ? `${movie.quality}` : ''}
`; }).join(''); } else { // No results searchGrid.innerHTML = `

No results found for "${query}"

`; } } catch (error) { console.error('Search failed:', error); searchLoading.style.display = 'none'; searchGrid.innerHTML = `

Search failed. Please try again.

`; } } /** * Setup search event listeners */ export function initSearch() { // Collect all possible search triggers const triggers = [ document.getElementById('headerSearchBtn'), document.getElementById('mobileSearchBtn'), document.querySelector('[data-view="search"]'), document.querySelector('button[data-view="search"]') // Mobile bottom nav ]; triggers.forEach(btn => { if (btn) { // Remove old listeners by cloning (simple way) or just add new one // Since we are shifting logic, just add listener btn.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); // Stop bubbling openSearchModal(); }); } }); // Close button if (closeSearch) { closeSearch.addEventListener('click', closeSearchModal); } // Backdrop click if (searchBackdrop) { searchBackdrop.addEventListener('click', closeSearchModal); } // Search input with debouncing if (searchInput) { searchInput.addEventListener('input', (e) => { clearTimeout(searchTimeout); const query = e.target.value; searchTimeout = setTimeout(() => { performSearch(query); }, SEARCH_DEBOUNCE_MS); }); // Enter key to search immediately searchInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') { clearTimeout(searchTimeout); performSearch(e.target.value); } }); } // Keyboard shortcuts document.addEventListener('keydown', (e) => { // Cmd/Ctrl + K to open search if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); openSearchModal(); } // Escape to close if (e.key === 'Escape' && searchModal.classList.contains('active')) { closeSearchModal(); } }); // Check for ?search= URL parameter and auto-perform search const urlParams = new URLSearchParams(window.location.search); const searchQuery = urlParams.get('search'); if (searchQuery && searchQuery.trim()) { // Open modal and perform search setTimeout(() => { openSearchModal(); if (searchInput) { searchInput.value = searchQuery; } performSearch(searchQuery); // Clean up the URL without refreshing const newUrl = window.location.pathname; window.history.replaceState({}, '', newUrl); }, 300); } } // Initialize on load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initSearch); } else { initSearch(); }