let videos = []; let currentCategory = 'All'; let searchInput, searchBtn, searchResults, searchResultsContent, videoGrid, shortsGrid, categoryBtns, subscriptionsList; async function init() { searchInput = document.querySelector('.search-input'); searchBtn = document.querySelector('.search-btn'); searchResults = document.querySelector('.search-results'); searchResultsContent = document.querySelector('.search-results-content'); videoGrid = document.querySelector('.video-grid'); shortsGrid = document.querySelector('.shorts-grid'); categoryBtns = document.querySelectorAll('.category-btn'); subscriptionsList = document.querySelector('.subscriptions-list'); await loadVideos(); if (videoGrid && shortsGrid) { renderVideos(); } if (subscriptionsList) { renderSubscriptions(); } bindEvents(); } async function loadVideos() { try { const response = await fetch('src/video.json'); const data = await response.json(); videos = data.videos; } catch (error) { console.error('Failed to load videos:', error); } } function renderVideos() { const filteredVideos = filterVideosByCategory(currentCategory); const videosOnly = filteredVideos.filter(video => video.type === 'video'); const shortsOnly = filteredVideos.filter(video => video.type === 'short'); videoGrid.innerHTML = ''; shortsGrid.innerHTML = ''; // Render long videos videosOnly.forEach(video => { const videoCard = createVideoCard(video); videoGrid.appendChild(videoCard); }); // Render shorts videos shortsOnly.forEach(video => { const shortsCard = createShortsCard(video); shortsGrid.appendChild(shortsCard); }); } function filterVideosByCategory(category) { if (category === 'All') { return videos; } const categoryMap = { 'Music': ['music'], 'Game': ['game'], 'Technology': ['tech'], 'Art': ['art'], 'Recently': videos.filter(v => v.uploadDate.includes('days ago')), 'Watched': [] }; if (categoryMap[category]) { if (Array.isArray(categoryMap[category]) && categoryMap[category].length > 0 && typeof categoryMap[category][0] === 'string') { return videos.filter(v => categoryMap[category].includes(v.category)); } else if (Array.isArray(categoryMap[category])) { return categoryMap[category]; } } return videos; } function createVideoCard(video) { const card = document.createElement('div'); card.className = 'video-card'; card.innerHTML = `
${video.title} ${video.duration}

${video.title}

${video.channel}
${video.views} views ${video.uploadDate}
`; const menuToggle = card.querySelector('.menu-toggle'); const menuDropdown = card.querySelector('.menu-dropdown'); menuToggle.addEventListener('click', (e) => { e.stopPropagation(); menuDropdown.classList.toggle('show'); }); document.addEventListener('click', () => { // Close the menu when clicking outside menuDropdown.classList.remove('show'); }); // Add click event to the card card.addEventListener('click', () => { window.location.href = `video.html?id=${video.id}`; }); return card; } function createShortsCard(video) { const card = document.createElement('div'); card.className = 'shorts-card'; card.innerHTML = `
${video.title}

${video.title}

${video.views} ${video.uploadDate}
`; // Add click event to the card card.addEventListener('click', () => { window.location.href = `short.html?id=${video.id}`; }); return card; } function renderSubscriptions() { // Render the subscriptions list const subscriptions = [ { name: '花譜 -KAF-', avatar: 'img/avatar/kaf.png' }, { name: 'ryo (supercell)', avatar: 'img/avatar/ryo.jpg' }, { name: 'ヰ世界情緒', avatar: 'img/avatar/isekaijoucho.jpg' }, { name: 'MyGo!!!!!', avatar: 'img/avatar/mygo.png' }, { name: 'ZUTOMAYO', avatar: 'img/avatar/ztmy.jpg' }, { name: 'Aqu3ra', avatar: 'img/avatar/aqu3ra.png' }, { name: '『超かぐや姫 ! 』公式', avatar: 'img/avatar/cpk.png' }, { name: '礼衣 / Rei', avatar: 'img/avatar/rei.jpg' }, { name: 'tayori', avatar: 'img/avatar/tayori.jpg' } ]; subscriptionsList.innerHTML = ''; subscriptions.forEach(sub => { const item = document.createElement('div'); item.className = 'subscription-item'; item.innerHTML = `
${sub.name}
${sub.name}
`; subscriptionsList.appendChild(item); }); } function performSearch(query) { // Perform the search and render the results if (!query.trim()) { searchResults.style.display = 'none'; return; } const results = videos.filter(video => video.title.toLowerCase().includes(query.toLowerCase()) || video.channel.toLowerCase().includes(query.toLowerCase()) ); renderSearchResults(results, query); } // Render the search results function renderSearchResults(results, query) { searchResultsContent.innerHTML = ''; if (results.length === 0) { searchResultsContent.innerHTML = '

No videos found related to your search.

'; searchResults.style.display = 'block'; return; } results.forEach(video => { const item = document.createElement('div'); item.className = 'search-result-item'; // Highlight the search keywords in the title and channel name const highlightedTitle = video.title.replace(new RegExp(`(${query})`, 'gi'), '$1'); const highlightedChannel = video.channel.replace(new RegExp(`(${query})`, 'gi'), '$1'); item.innerHTML = `
${video.title}

${highlightedTitle}

${highlightedChannel}
${video.views} views · ${video.uploadDate}
`; // Add click event to the search result item item.addEventListener('click', () => { window.location.href = `video.html?id=${video.id}`; }); searchResultsContent.appendChild(item); }); searchResults.style.display = 'block'; } // Bind events to the DOM elements function bindEvents() { // Bind events to the DOM elements // Menu button event - toggle sidebar const menuBtn = document.querySelector('.menu-btn'); const sidebar = document.querySelector('.sidebar'); if (menuBtn && sidebar) { menuBtn.addEventListener('click', () => { sidebar.classList.toggle('collapsed'); }); } // Search event if (searchInput) { searchInput.addEventListener('input', (e) => { performSearch(e.target.value); }); } if (searchBtn) { searchBtn.addEventListener('click', () => { performSearch(searchInput ? searchInput.value : ''); }); } // Close the search results when clicking outside if (searchResults) { document.addEventListener('click', (e) => { if (!e.target.closest('.search-container') && !e.target.closest('.search-results')) { searchResults.style.display = 'none'; } }); } // Category buttons event if (categoryBtns.length > 0) { categoryBtns.forEach(btn => { btn.addEventListener('click', () => { // Remove all active states categoryBtns.forEach(b => b.classList.remove('active')); // Add current active state btn.classList.add('active'); // Update current category currentCategory = btn.textContent; // Re-render videos and shorts if (videoGrid && shortsGrid) { renderVideos(); } }); }); } // Sidebar navigation buttons event const navBtns = document.querySelectorAll('.nav-btn'); if (navBtns.length > 0) { navBtns.forEach(btn => { btn.addEventListener('click', () => { // Remove all active states navBtns.forEach(b => b.classList.remove('active')); // Add current active state btn.classList.add('active'); }); }); } // Subscription section expand/collapse event const subscriptionTitle = document.querySelector('.nav-section-title'); if (subscriptionTitle) { subscriptionTitle.addEventListener('click', () => { const subscriptionsList = document.querySelector('.subscriptions-list'); const chevron = subscriptionTitle.querySelector('i'); if (subscriptionsList && chevron) { subscriptionsList.classList.toggle('collapsed'); if (subscriptionsList.classList.contains('collapsed')) { chevron.style.transform = 'rotate(-90deg)'; } else { chevron.style.transform = 'rotate(0deg)'; } } }); } } // Page load event: initialize the application window.addEventListener('DOMContentLoaded', init);