From 741b73c12f2487ba7e2cee54c58d3d854d3bc85d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:09:23 +0000 Subject: [PATCH] feat: Optimize PDF search filtering with pre-computed index and early returns - Added `prepareSearchIndex` function to pre-compute lowercase search strings. - Updated `loadPDFDatabase` to call `prepareSearchIndex` after data load. - Refactored `renderPDFs` to use the pre-computed index and short-circuit logic. - Ensured `_searchStr` is non-enumerable to avoid polluting localStorage cache. Co-authored-by: MrAlokTech <107493955+MrAlokTech@users.noreply.github.com> --- script.js | 52 ++++++++++++++++++++++++++----------- verification_functions.png | Bin 0 -> 8700 bytes verification_initial.png | Bin 0 -> 9041 bytes verification_search.png | Bin 0 -> 8936 bytes 4 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 verification_functions.png create mode 100644 verification_initial.png create mode 100644 verification_search.png diff --git a/script.js b/script.js index bdc06f3..bf24453 100644 --- a/script.js +++ b/script.js @@ -413,6 +413,27 @@ async function syncClassSwitcher() { renderSemesterTabs(); } +function prepareSearchIndex() { + if (!pdfDatabase || !Array.isArray(pdfDatabase)) return; + + pdfDatabase.forEach(pdf => { + // Optimization: Pre-compute search string to avoid repetitive toLowerCase() calls in render loop + // We use a non-enumerable property so it doesn't get serialized to localStorage + const searchStr = [ + pdf.title, + pdf.description, + pdf.category, + pdf.author + ].map(s => (s || '').toLowerCase()).join(' '); + + Object.defineProperty(pdf, '_searchStr', { + value: searchStr, + enumerable: false, + writable: true + }); + }); +} + async function loadPDFDatabase() { if (isMaintenanceActive) return; @@ -451,6 +472,7 @@ async function loadPDFDatabase() { if (shouldUseCache) { pdfDatabase = cachedData; + prepareSearchIndex(); // --- FIX: CALL THIS TO POPULATE UI --- syncClassSwitcher(); renderSemesterTabs(); @@ -474,6 +496,8 @@ async function loadPDFDatabase() { data: pdfDatabase })); + prepareSearchIndex(); + // --- FIX: CALL THIS TO POPULATE UI --- syncClassSwitcher(); renderPDFs(); @@ -902,26 +926,24 @@ function renderPDFs() { // Locate renderPDFs() in script.js and update the filter section const filteredPdfs = pdfDatabase.filter(pdf => { - const matchesSemester = pdf.semester === currentSemester; - - // NEW: Check if the PDF class matches the UI's current class selection - // Note: If old documents don't have this field, they will be hidden. - const matchesClass = pdf.class === currentClass; + // Optimization: Early returns to skip expensive checks + if (pdf.class !== currentClass) return false; + if (pdf.semester !== currentSemester) return false; - let matchesCategory = false; if (currentCategory === 'favorites') { - matchesCategory = favorites.includes(pdf.id); - } else { - matchesCategory = currentCategory === 'all' || pdf.category === currentCategory; + if (!favorites.includes(pdf.id)) return false; + } else if (currentCategory !== 'all' && pdf.category !== currentCategory) { + return false; } - const matchesSearch = pdf.title.toLowerCase().includes(searchTerm) || - pdf.description.toLowerCase().includes(searchTerm) || - pdf.category.toLowerCase().includes(searchTerm) || - pdf.author.toLowerCase().includes(searchTerm); + // Use pre-computed search string + if (pdf._searchStr) { + return pdf._searchStr.includes(searchTerm); + } - // Update return statement to include matchesClass - return matchesSemester && matchesClass && matchesCategory && matchesSearch; + // Fallback for safety (should rarely happen if prepareSearchIndex ran) + const rawSearch = (pdf.title || '') + " " + (pdf.description || '') + " " + (pdf.category || '') + " " + (pdf.author || ''); + return rawSearch.toLowerCase().includes(searchTerm); }); updatePDFCount(filteredPdfs.length); diff --git a/verification_functions.png b/verification_functions.png new file mode 100644 index 0000000000000000000000000000000000000000..51e9323b72fdc6e49b66d0d4d86e872f731c72c7 GIT binary patch literal 8700 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 literal 0 HcmV?d00001 diff --git a/verification_initial.png b/verification_initial.png new file mode 100644 index 0000000000000000000000000000000000000000..549b24745ded3984c972131880119c4342b7784e GIT binary patch literal 9041 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 literal 0 HcmV?d00001 diff --git a/verification_search.png b/verification_search.png new file mode 100644 index 0000000000000000000000000000000000000000..5e6d84850dfca2f55911a11b33b5155458fe5d9c GIT binary patch literal 8936 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 MY|oYa=63JD0dp1VT>t<8 literal 0 HcmV?d00001