From cfb6b5aa85cf9105189d889859141dc4f917ac9a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 13:34:58 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Optimize=20search=20filtering=20wit?= =?UTF-8?q?h=20pre-calculation=20and=20debounce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added `debounce` utility to reduce render frequency on search input. - Added `prepareSearchIndex` to pre-calculate search strings and date formats on data load. - Updated `renderPDFs` to use the optimized `_searchStr` property. - Updated `createPDFCard` to use pre-calculated `_formattedDate` and `_isNew` values. - Reduces main thread work during search and scrolling. Co-authored-by: MrAlokTech <107493955+MrAlokTech@users.noreply.github.com> --- script.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/script.js b/script.js index bdc06f3..17f0441 100644 --- a/script.js +++ b/script.js @@ -247,6 +247,15 @@ function getSimpleDeviceName() { /* ========================================= 4. UI HELPERS & ADS ========================================= */ +function debounce(func, wait) { + let timeout; + return function(...args) { + const context = this; + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(context, args), wait); + }; +} + function handleGoToTopVisibility() { if (window.scrollY > 400) { goToTopBtn.classList.add('show'); @@ -382,6 +391,36 @@ window.changeSemester = function (sem) { renderPDFs(); }; +function prepareSearchIndex(pdfs) { + const now = new Date(); + pdfs.forEach(pdf => { + // Optimization: Pre-calculate search string + pdf._searchStr = ( + (pdf.title || '') + ' ' + + (pdf.description || '') + ' ' + + (pdf.category || '') + ' ' + + (pdf.author || '') + ).toLowerCase(); + + // Optimization: Pre-calculate date values + let dateObj; + // Handle Firestore Timestamp or String + if (pdf.uploadDate && typeof pdf.uploadDate.toDate === 'function') { + dateObj = pdf.uploadDate.toDate(); + } else { + dateObj = new Date(pdf.uploadDate); + } + + // Optimization: Cache formatted date string + pdf._formattedDate = dateObj.toLocaleDateString('en-US', { + year: 'numeric', month: 'short', day: 'numeric' + }); + + const timeDiff = now - dateObj; + pdf._isNew = timeDiff < (7 * 24 * 60 * 60 * 1000); // 7 days + }); +} + async function syncClassSwitcher() { const classSelect = document.getElementById('classSelect'); if (!classSelect) return; @@ -451,6 +490,7 @@ async function loadPDFDatabase() { if (shouldUseCache) { pdfDatabase = cachedData; + prepareSearchIndex(pdfDatabase); // --- FIX: CALL THIS TO POPULATE UI --- syncClassSwitcher(); renderSemesterTabs(); @@ -474,6 +514,8 @@ async function loadPDFDatabase() { data: pdfDatabase })); + prepareSearchIndex(pdfDatabase); + // --- FIX: CALL THIS TO POPULATE UI --- syncClassSwitcher(); renderPDFs(); @@ -656,7 +698,7 @@ function activateHoliday(overlay) { 7. EVENT LISTENERS ========================================= */ function setupEventListeners() { - searchInput.addEventListener('input', renderPDFs); + searchInput.addEventListener('input', debounce(renderPDFs, 300)); tabBtns.forEach(btn => { btn.addEventListener('click', handleSemesterChange); @@ -915,10 +957,14 @@ function renderPDFs() { matchesCategory = currentCategory === 'all' || pdf.category === currentCategory; } - const matchesSearch = pdf.title.toLowerCase().includes(searchTerm) || + // Optimization: Use pre-calculated search string + const matchesSearch = pdf._searchStr ? pdf._searchStr.includes(searchTerm) : ( + // Fallback for safety + pdf.title.toLowerCase().includes(searchTerm) || pdf.description.toLowerCase().includes(searchTerm) || pdf.category.toLowerCase().includes(searchTerm) || - pdf.author.toLowerCase().includes(searchTerm); + pdf.author.toLowerCase().includes(searchTerm) + ); // Update return statement to include matchesClass return matchesSemester && matchesClass && matchesCategory && matchesSearch; @@ -991,9 +1037,8 @@ function createPDFCard(pdf, favoritesList, index = 0, highlightRegex = null) { const heartIconClass = isFav ? 'fas' : 'far'; const btnActiveClass = isFav ? 'active' : ''; - const uploadDateObj = new Date(pdf.uploadDate); - const timeDiff = new Date() - uploadDateObj; - const isNew = timeDiff < (7 * 24 * 60 * 60 * 1000); // 7 days + // Optimization: Use pre-calculated isNew flag + const isNew = pdf._isNew !== undefined ? pdf._isNew : (new Date() - new Date(pdf.uploadDate) < (7 * 24 * 60 * 60 * 1000)); const newBadgeHTML = isNew ? `NEW` @@ -1008,7 +1053,8 @@ function createPDFCard(pdf, favoritesList, index = 0, highlightRegex = null) { const categoryIcon = categoryIcons[pdf.category] || 'fa-file-pdf'; // Formatting Date - const formattedDate = new Date(pdf.uploadDate).toLocaleDateString('en-US', { + // Optimization: Use pre-formatted date string + const formattedDate = pdf._formattedDate || new Date(pdf.uploadDate).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' });