PageSourceSearch

https://plazi.org/js/search-mini.js

js plazi.org collected 2026-09-24 08:25:33 UTC 4,362 bytes, 155 lines download raw bytes

1let searchVisible = true; 
2
3// allow us to delay loading json data unless search activated
4let firstRun = true;
5
6// targets the <ul>
7const list = document.getElementById('searchResults'); 
8
9// first child of search list
10let first = list.firstChild; 
11
12// last child of search list
13let last = list.lastChild; 
14
15// input box for search
16const maininput = document.getElementById('searchInput'); 
17
18// Did we get any search results?
19let resultsAvailable = false; 
20
21if(firstRun) {
22
23    // loads our json data and builds the search index
24    loadSearch(); 
25
26    // let's never do this again
27    firstRun = false; 
28}
29
30const stopWords = new Set(['and', 'or', 'to', 'in', 'a', 'the', /* ...and more */ ]);
31
32// Perform custom term processing (here discarding stop words and downcasing)
33let miniSearch = new MiniSearch({
34
35    // fields to index for full-text search
36    fields: ['contents'],
37
38    processTerm: (term, _fieldName) => stopWords.has(term) ? null : term.toLowerCase(),
39
40    searchOptions: {
41        boost: { title: 2 },
42        fuzzy: 0.2
43    },
44
45    // fields to return with search results
46    storeFields: ['title', 'contents', 'permalink'] 
47});
48
49// ==========================================
50// execute search as each character is typed
51//
52document.getElementById("searchInput").onkeyup = function(e) { 
53    executeSearch(this.value);
54}
55
56function fetchJSONFile(path, callback) {
57    const httpRequest = new XMLHttpRequest();
58    httpRequest.onreadystatechange = function() {
59        if (httpRequest.readyState === 4) {
60            if (httpRequest.status === 200) {
61                const data = JSON.parse(httpRequest.responseText);
62                if (callback) callback(data);
63            }
64        }
65    };
66
67    httpRequest.open('GET', path);
68    httpRequest.send(); 
69  }
70
71function loadSearch() {
72    fetchJSONFile('/index.json', function(data){
73        miniSearch.addAll(data);
74    });
75}
76
77function executeSearch(term) {
78  
79    // the actual query being run using miniSearch.js
80    let results = miniSearch.search(term); 
81    
82    // our results bucket
83    let searchitems = ''; 
84
85    // no results based on what was typed into the input box
86    if (results.length === 0) { 
87        resultsAvailable = false;
88    } 
89
90    // build our html
91    else {
92
93        // https://stackoverflow.com/a/36744732/183692
94        // dedupe the results based on permalink
95        results = results.filter((value, index, self) =>
96            index === self.findIndex((t) => (
97                t.title === value.title
98            ))
99        );
100
101        //console.log(`results" ${results.length}`)
102
103        const snippetLength = 400;
104        const side = snippetLength / 2;
105
106        results.forEach(item => {
107
108//         contents: "…"
109//         id: 32
110//         match: Object { digitize: (1) […] }
111//         permalink: "http://localhost:1313/posts/bhl-and-plazi-partnership/"
112//         score: 1.7846304978818683
113//         terms: Array [ "digitize" ]
114//         title: "BHL and Plazi partnership"
115
116        //const item = i.item;
117        const terms = item.terms;
118        const permalink = item.permalink;
119        const title = item.title;
120        //let content = item.contents.substring(0, 200);
121        let content = item.contents;
122
123        terms.forEach(term => {
124            const re = new RegExp(`(${term})`, 'i');
125            const matchInfo = content.match(re);
126            const left = matchInfo.index - side;
127            const right = matchInfo.index + term.length + side;
128            content = content.substring(left, right);
129            //content = content.replace(re, '<span class="hilite">$1</span>');
130            content = content.replace(re, '<mark>$1</mark>');
131        })
132        
133  
134        searchitems = searchitems + 
135            `<li>
136            <a href="${permalink}" tabindex="0">
137                <h2 class="title">${title}</h2>
138                <p>${content}…</p>
139            </a>
140            </li>`
141        });
142  
143        resultsAvailable = true;
144    }
145  
146    document.getElementById("searchResults").innerHTML = searchitems;
147    if (results.length > 0) {
148
149        // first result container — used for checking against keyboard up/down location
150        first = list.firstChild.firstElementChild; 
151
152        // last result container — used for checking against keyboard up/down location
153        last = list.lastChild.firstElementChild; 
154    }
155}

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.