const searchInput = document.getElementById('search-input'); const searchResults = document.getElementById('search-results'); let searchTimeout; searchInput.addEventListener('input', (e) => { const query = e.target.value; clearTimeout(searchTimeout); if (query.length < 2) { searchResults.classList.remove('active'); searchResults.innerHTML = ''; searchInput.style.borderRadius = '99px'; return; } searchTimeout = setTimeout(() => { fetchSearh(query); }, 300); }); document.addEventListener('click', (e) => { if (!e.target.closest('.search-wrapper')) { searchResults.classList.remove('active'); searchInput.style.borderRadius = '99px'; } }); async function fetchSearh(query) { try { const res = await fetch(`/api/search?q=${encodeURIComponent(query.slice(0, 30))}`); const data = await res.json(); renderSearchResults(data.results); } catch (err) { console.error("Search Error:", err); } } function createSlug(text) { if (!text) return ''; return text .toLowerCase() .trim() .replace(/-/g, '--') .replace(/\s+/g, '-') .replace(/[^a-z0-9\-]/g, ''); } function renderSearchResults(results) { searchResults.innerHTML = ''; if (results.length === 0) { searchResults.innerHTML = '
No results found
'; } else { results.forEach(anime => { const title = getTitle(anime); const img = anime.coverImage.medium || anime.coverImage.large; const rating = anime.averageScore ? `${anime.averageScore}%` : 'N/A'; const year = anime.seasonYear || ''; const format = anime.format || 'TV'; let href; if (anime.isExtensionResult) { const titleSlug = createSlug(title); console.log(title); href = `/anime/${anime.extensionName}/${titleSlug}`; } else { href = `/anime/${anime.id}`; } const extName = anime.extensionName?.charAt(0).toUpperCase() + anime.extensionName?.slice(1); const extPill = anime.isExtensionResult ? `• ${extName}` : ''; const item = document.createElement('a'); item.className = 'search-item'; item.href = href; item.innerHTML = ` ${title}
${title}
${rating} • ${year} • ${format} ${extPill}
`; searchResults.appendChild(item); }); } searchResults.classList.add('active'); searchInput.style.borderRadius = '12px 12px 0 0'; } function scrollCarousel(id, direction) { const container = document.getElementById(id); if(container) { const scrollAmount = container.clientWidth * 0.75; container.scrollBy({ left: direction * scrollAmount, behavior: 'smooth' }); } } let trendingAnimes = []; let currentHeroIndex = 0; let player; let heroInterval; var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); function onYouTubeIframeAPIReady() { player = new YT.Player('player', { height: '100%', width: '100%', playerVars: { 'autoplay': 1, 'controls': 0, 'mute': 1, 'loop': 1, 'showinfo': 0, 'modestbranding': 1 }, events: { 'onReady': (e) => { e.target.mute(); if(trendingAnimes.length) updateHeroVideo(trendingAnimes[currentHeroIndex]); } } }); } async function fetchContent(isUpdate = false) { try { const trendingRes = await fetch('/api/trending'); const trendingData = await trendingRes.json(); if (trendingData.results && trendingData.results.length > 0) { trendingAnimes = trendingData.results; if (!isUpdate) { updateHeroUI(trendingAnimes[0]); startHeroCycle(); } renderList('trending', trendingAnimes); } else if (!isUpdate) { setTimeout(() => fetchContent(false), 2000); } const topRes = await fetch('/api/top-airing'); const topData = await topRes.json(); if (topData.results && topData.results.length > 0) { renderList('top-airing', topData.results); } } catch (e) { console.error("Fetch Error:", e); if(!isUpdate) setTimeout(() => fetchContent(false), 5000); } } function startHeroCycle() { if(heroInterval) clearInterval(heroInterval); heroInterval = setInterval(() => { if(trendingAnimes.length > 0) { currentHeroIndex = (currentHeroIndex + 1) % trendingAnimes.length; updateHeroUI(trendingAnimes[currentHeroIndex]); } }, 10000); } function getTitle(anime) { return anime.title.english || anime.title.romaji || "Unknown Title"; } function updateHeroUI(anime) { if(!anime) return; const title = getTitle(anime); const score = anime.averageScore ? anime.averageScore + '% Match' : 'N/A'; const year = anime.seasonYear || ''; const type = anime.format || 'TV'; const desc = anime.description || 'No description available.'; const poster = anime.coverImage ? anime.coverImage.extraLarge : ''; const banner = anime.bannerImage || poster; document.getElementById('hero-title').innerText = title; document.getElementById('hero-desc').innerHTML = desc; document.getElementById('hero-score').innerText = score; document.getElementById('hero-year').innerText = year; document.getElementById('hero-type').innerText = type; document.getElementById('hero-poster').src = poster; const watchBtn = document.getElementById('watch-btn'); if(watchBtn) watchBtn.onclick = () => window.location.href = `/anime/${anime.id}`; const bgImg = document.getElementById('hero-bg-media'); if(bgImg && bgImg.src !== banner) bgImg.src = banner; updateHeroVideo(anime); document.getElementById('hero-loading-ui').style.display = 'none'; document.getElementById('hero-real-ui').style.display = 'block'; } function updateHeroVideo(anime) { if (!player || !player.loadVideoById) return; const videoContainer = document.getElementById('player'); if (anime.trailer && anime.trailer.site === 'youtube' && anime.trailer.id) { if(player.getVideoData && player.getVideoData().video_id !== anime.trailer.id) { player.loadVideoById(anime.trailer.id); player.mute(); } videoContainer.style.opacity = "1"; } else { videoContainer.style.opacity = "0"; player.stopVideo(); } } function renderList(id, list) { const container = document.getElementById(id); const firstId = list.length > 0 ? list[0].id : null; const currentFirstId = container.firstElementChild?.dataset?.id; if (currentFirstId && parseInt(currentFirstId) === firstId && container.children.length === list.length) { return; } container.innerHTML = ''; list.forEach(anime => { const title = getTitle(anime); const cover = anime.coverImage ? anime.coverImage.large : ''; const ep = anime.nextAiringEpisode ? 'Ep ' + anime.nextAiringEpisode.episode : (anime.episodes ? anime.episodes + ' Eps' : 'TV'); const score = anime.averageScore || '--'; const el = document.createElement('div'); el.className = 'card'; el.dataset.id = anime.id; el.onclick = () => window.location.href = `/anime/${anime.id}`; el.innerHTML = `

${title}

${score}% • ${ep}

`; container.appendChild(el); }); } fetchContent(); setInterval(() => fetchContent(true), 60000);