// Pagination state
let allArticles = [];
let filteredArticles = [];
let displayedCount = 0;
const ARTICLES_PER_PAGE = 5;
let isLoading = false;
let searchQuery = '';
// Load news on page load
document.addEventListener('DOMContentLoaded', () => {
loadNews();
loadStats();
setupInfiniteScroll();
});
async function loadNews() {
const newsGrid = document.getElementById('newsGrid');
newsGrid.innerHTML = '
Loading news...
';
try {
const response = await fetch('/api/news');
const data = await response.json();
if (data.articles && data.articles.length > 0) {
allArticles = data.articles;
filteredArticles = data.articles;
displayedCount = 0;
newsGrid.innerHTML = '';
updateSearchStats();
loadMoreArticles();
} else {
newsGrid.innerHTML = 'No news available at the moment. Check back later!
';
}
} catch (error) {
console.error('Error loading news:', error);
newsGrid.innerHTML = 'Failed to load news. Please try again later.
';
}
}
function loadMoreArticles() {
if (isLoading || displayedCount >= filteredArticles.length) return;
isLoading = true;
const newsGrid = document.getElementById('newsGrid');
// Remove loading indicator if exists
const loadingIndicator = document.getElementById('loadingIndicator');
if (loadingIndicator) loadingIndicator.remove();
// Get next batch of articles
const nextBatch = filteredArticles.slice(displayedCount, displayedCount + ARTICLES_PER_PAGE);
nextBatch.forEach((article, index) => {
const card = createNewsCard(article, displayedCount + index);
newsGrid.appendChild(card);
});
displayedCount += nextBatch.length;
// Add loading indicator if more articles available
if (displayedCount < filteredArticles.length) {
const loader = document.createElement('div');
loader.id = 'loadingIndicator';
loader.className = 'text-center py-8 text-gray-400';
loader.innerHTML = 'Loading more...
';
newsGrid.appendChild(loader);
} else if (filteredArticles.length > 0) {
// Add end message
const endMessage = document.createElement('div');
endMessage.className = 'text-center py-8 text-gray-400 text-sm';
endMessage.textContent = `✓ All ${filteredArticles.length} articles loaded`;
newsGrid.appendChild(endMessage);
}
isLoading = false;
}
function setupInfiniteScroll() {
window.addEventListener('scroll', () => {
if (isLoading || displayedCount >= filteredArticles.length) return;
const scrollPosition = window.innerHeight + window.scrollY;
const threshold = document.documentElement.scrollHeight - 500;
if (scrollPosition >= threshold) {
loadMoreArticles();
}
});
}
// Search functionality
function handleSearch() {
const searchInput = document.getElementById('searchInput');
const clearBtn = document.getElementById('clearSearch');
searchQuery = searchInput.value.trim().toLowerCase();
// Show/hide clear button
if (searchQuery) {
clearBtn.classList.remove('hidden');
} else {
clearBtn.classList.add('hidden');
}
// Filter articles
if (searchQuery === '') {
filteredArticles = allArticles;
} else {
filteredArticles = allArticles.filter(article => {
const title = article.title.toLowerCase();
const summary = (article.summary || '').toLowerCase().replace(/<[^>]*>/g, '');
const source = formatSourceName(article.source).toLowerCase();
return title.includes(searchQuery) ||
summary.includes(searchQuery) ||
source.includes(searchQuery);
});
}
// Reset display
displayedCount = 0;
const newsGrid = document.getElementById('newsGrid');
newsGrid.innerHTML = '';
// Update stats
updateSearchStats();
// Load filtered articles
if (filteredArticles.length > 0) {
loadMoreArticles();
} else {
newsGrid.innerHTML = `
🔍
No articles found
Try a different search term
`;
}
}
function clearSearch() {
const searchInput = document.getElementById('searchInput');
searchInput.value = '';
handleSearch();
searchInput.focus();
}
function updateSearchStats() {
const searchStats = document.getElementById('searchStats');
if (searchQuery) {
searchStats.textContent = `Found ${filteredArticles.length} of ${allArticles.length} articles`;
} else {
searchStats.textContent = `Showing ${allArticles.length} articles`;
}
}
function createNewsCard(article, index) {
const card = document.createElement('div');
card.className = 'group bg-white rounded-xl overflow-hidden shadow-md hover:shadow-xl transition-all duration-300 cursor-pointer border border-gray-100 hover:border-primary/30';
card.onclick = () => window.open(article.link, '_blank');
// Extract image from summary if it's an img tag (from Süddeutsche)
let imageUrl = null;
let cleanSummary = article.summary || 'No summary available.';
if (cleanSummary.includes('