1/* Search Module JS */ 2 3document.addEventListener("DOMContentLoaded", () => { 4 // 1. Filter Initialization 5 const categorySelect = document.querySelector('select[name="category"]'); 6 const authorSelect = document.querySelector('select[name="author"]'); 7 8 if (typeof hatchSearchData === 'undefined') return; 9 10 if (categorySelect && hatchSearchData.category) { 11 categorySelect.value = hatchSearchData.category; 12 } 13 14 if (authorSelect && hatchSearchData.author) { 15 authorSelect.value = hatchSearchData.author; 16 } 17 18 // 2. Infinite Scroll Logic 19 let currentPage = 1; 20 let isLoading = false; 21 const resultsContainer = document.querySelector("#search-results-container"); 22 const loadingAnimation = document.querySelector(".loading-animation"); 23 const noMoreResults = document.querySelector(".no-more-results"); 24 const currentCountDisplay = document.querySelector("#current-count"); 25 const totalCountDisplay = document.querySelector("#total-count"); 26 const loadMoreHint = document.querySelector("#load-more-hint"); 27 28 const updateCounter = () => { 29 const currentCount = document.querySelectorAll(".result-item").length; 30 if (currentCountDisplay) currentCountDisplay.textContent = currentCount; 31 32 const totalCount = hatchSearchData.total_posts || (totalCountDisplay ? parseInt(totalCountDisplay.textContent) : 0); 33 if (totalCountDisplay) totalCountDisplay.textContent = totalCount; 34 35 if (loadMoreHint) { 36 loadMoreHint.style.display = (currentCount < totalCount) ? "inline" : "none"; 37 } 38 }; 39
40 const loadMoreResults = () => { 41 if (isLoading) return; 42 43 isLoading = true; 44 if (loadingAnimation) { 45 loadingAnimation.style.display = "block"; 46 } 47 48 const data = new URLSearchParams({ 49 action: "load_more_results", 50 nonce: hatchSearchData.nonce, 51 page: ++currentPage, 52 query: hatchSearchData.query, 53 category: hatchSearchData.category, 54 author: hatchSearchData.author 55 }); 56 57 fetch(hatchSearchData.ajaxUrl, { 58 method: "POST", 59 body: data, 60 headers: { 61 "Content-Type": "application/x-www-form-urlencoded" 62 } 63 }) 64 .then((res) => { 65 if (!res.ok) throw new Error("HTTP " + res.status); 66 return res.text(); 67 }) 68 .then((html) => { 69 isLoading = false; 70 71 // Nunca inyectar la respuesta si no trae resultados reales: admin-ajax 72 // devuelve "-1" (nonce/permisos) o "0" (acción desconocida) en texto 73 // plano, y antes se pegaban tal cual en la grilla ("-1-1-1-1..."). 74 if (!html.includes("result-item") || html.includes("no-more-results")) { 75 isLoading = true; // Stop further calls 76 if (loadingAnimation) loadingAnimation.style.display = "none"; 77 if (noMoreResults) { 78 noMoreResults.style.display = "block"; 79 } 80 return; 81 } 82 83 if (resultsContainer) { 84 resultsContainer.insertAdjacentHTML("beforeend", html); 85 updateCounter(); 86 87 // Hide loading animation after successful append 88 if (loadingAnimation) loadingAnimation.style.display = "none"; 89 } 90 }) 91 .catch((error) => { 92 console.error("Error loading more results:", error); 93 currentPage--; // Reintentar la misma página, no saltársela 94 isLoading = false; 95 if (loadingAnimation) { 96 loadingAnimation.style.display = "none"; 97 } 98 }); 99 }; 100 101 // Only add scroll listener if we are on the results page 102 if (resultsContainer) { 103 window.addEventListener("scroll", () => { 104 if ( 105 !isLoading && 106 document.documentElement.scrollHeight - document.documentElement.scrollTop <= 107 document.documentElement.clientHeight + 600 108 ) { 109 loadMoreResults(); 110 } 111 }); 112 } 113});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.