PageSourceSearch

https://www.truenas.com/docs/js/search.js

js truenas.com collected 2026-10-02 02:34:24 UTC 4,742 bytes, 115 lines download raw bytes

1let query = new URLSearchParams(window.location.search).get("query");
2let searchResultsContainer = document.getElementById('results');
3let currentPage = 1;
4const resultsPerPage = 10;
5let pagefind;
6let loadMoreButton; // Cache reference to the load more button
7
8initPageFind();
9
10async function initPageFind() {
11    pagefind = await import("https://www.truenas.com/docs/pagefind/pagefind.js");
12    pagefind.init();
13
14    if (query != null) {
15        document.getElementById("search-input").value = query;
16        await displaySearchResults(query, currentPage);
17    }
18}
19
20async function displaySearchResults(query, page) {
21    try {
22        let results = await pagefind.search(query);
23        let paginatedResults = results.results;
24        let slicedResults = await Promise.all(paginatedResults.map(r => r.data()));
25
26        let startIndex = (page - 1) * resultsPerPage;
27        let endIndex = startIndex + resultsPerPage;
28        let paginatedSlicedResults = slicedResults.slice(startIndex, endIndex);
29
30        if (loadMoreButton) {
31            loadMoreButton.classList.remove("loading");
32        }
33
34        if (paginatedSlicedResults.length === 0) {
35            if (currentPage === 1) {
36                searchResultsContainer.innerHTML = 'No results found.';
37            } else {
38                let noMoreResultsMessage = document.createElement('div');
39                noMoreResultsMessage.innerHTML = '<p>No more results.</p>';
40                searchResultsContainer.appendChild(noMoreResultsMessage);
41            }
42        } else {
43            let fragment = document.createDocumentFragment();
44
45            paginatedSlicedResults.forEach((result, index) => {
46                let resultDiv = document.createElement('div');
47                let title = result.meta.title.charAt(0).toUpperCase() + result.meta.title.slice(1);
48
49                // Add section marker in front of the <a>
50                let coreIcon = '<img src="https://www.truenas.com/docs/favicon/TN-favicon-32x32.png" alt="TrueNAS CORE" title="TrueNAS CORE" class="icon">';
51                let scaleIcon = '<img src="https://www.truenas.com/docs/favicon/TN-favicon-32x32.png" alt="TrueNAS" title="TrueNAS" class="icon">';
52                let tcIcon = '<img src="https://www.truenas.com/docs/favicon/TC-favicon-32x32.png" alt="TrueCommand" title="TrueCommand" class="icon">';
53
54                let linkText = result.url.includes("/core/") ? `${coreIcon}`
55                    : result.url.includes("/scale/") ? `${scaleIcon}`
56                    : result.url.includes("/truecommand/") ? `${tcIcon}`
57                    : result.url.includes("/solutions/") ? `Solutions:`
58                    : result.url.includes("/hardware/") ? `TrueNAS Systems:`
59                    : result.url.includes("/contributing/") ? `Contributing:`
60                    : result.url.includes("/references/") ? `References:`
61					: result.url.includes("core_websocket") ? `${coreIcon}\u00A0API:`
62					: result.url.includes("scale_websocket") ? `${scaleIcon}\u00A0API:`
63                    : `${title}:`;
64
65                resultDiv.innerHTML = `
66                    <h3>${linkText}&ensp;<a href="${result.url}">${title}</a></h3>
67                    <p>${result.excerpt}</p>
68                    <hr>
69                `;
70                fragment.appendChild(resultDiv);
71            });
72
73            // Append the new results fragment to existing content
74            searchResultsContainer.appendChild(fragment);
75
76            // Check if there are more results to display
77            const hasMoreResults = slicedResults.length > endIndex;
78
79            // Show/hide the load more button
80            if (hasMoreResults) {
81                if (!loadMoreButton) {
82                    loadMoreButton = createLoadMoreButton();
83                }
84                loadMoreButton.classList.remove("loading");
85                loadMoreButton.style.display = 'block';
86            } else if (loadMoreButton) {
87                loadMoreButton.style.display = 'none';
88            }
89        }
90
91    } catch (error) {
92        console.error('Error:', error);
93        throw error;
94    }
95}
96
97async function loadMoreResults() {
98    currentPage++;
99    let query = new URLSearchParams(window.location.search).get("query");
100    if (loadMoreButton) {
101        loadMoreButton.classList.add("loading");
102    }
103    await displaySearchResults(query, currentPage);
104}
105
106function createLoadMoreButton() {
107    const button = document.createElement("a");
108    button.classList.add("absolute-center");
109    button.classList.add("button");
110    button.textContent = "Load more results";
111    button.id = "loadMoreButton";
112    button.addEventListener('click', loadMoreResults);
113    searchResultsContainer.parentNode.appendChild(button);
114    return button;
115}

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.