From 3af6d9131f6dfc138856d718ec96626344095ec8 Mon Sep 17 00:00:00 2001 From: Jieiku Date: Mon, 22 May 2023 23:24:44 -0700 Subject: Optimizations and Fixes --- static/search.js | 369 ------------------------------------------------------- 1 file changed, 369 deletions(-) delete mode 100644 static/search.js (limited to 'static/search.js') diff --git a/static/search.js b/static/search.js deleted file mode 100644 index da46986..0000000 --- a/static/search.js +++ /dev/null @@ -1,369 +0,0 @@ -// in page results when press enter or click search icon from search box -function closeSearchNow() { - const main = document.querySelector("main"); - main.innerHTML = window.main -} - -function goSearchNow() { - const main = document.querySelector("main"); - if (!window.main) { - window.main = main.innerHTML - }; - var results = document.getElementById("suggestions");// suggestions div generated by search box - - var ResultsClone = results.cloneNode(true);// make a clone of the results, so that we can alter it - ResultsClone.id = "results";// alter the id of our clone, so that we can apply different css style - - var headerDiv = document.createElement("div");// create a div element - - var headerContent = '

Results For: '.concat(document.getElementById("searchinput").value, "

");// header to use at top of results page - - headerDiv.innerHTML = headerContent;// document element div (headerDiv), set the inner contents to our header html (headerContent) - - ResultsClone.insertBefore(headerDiv, ResultsClone.firstChild);//insert our header div at the top of the page - - main.innerHTML = ResultsClone.outerHTML;//display ResultsClone.outerHTML as the page - results.innerHTML = "";// clear the suggestions div popup - document.getElementById("searchinput").value = "";// clear the search input box - document.body.contains(document.closeSearch) && (document.closeSearch.onsubmit = function() { closeSearchNow() }) - return false -} - -/* Close search suggestion popup list */ -function closeAllLists(elmnt) { - var suggestions = document.getElementById("suggestions"); - while (suggestions.firstChild) { - suggestions.removeChild(suggestions.firstChild); - } -} - -function inputFocus(e) { - - if (e.keyCode === 191//forward slash - && document.activeElement.tagName !== "INPUT" - && document.activeElement.tagName !== "TEXTAREA") { - e.preventDefault(); - searchinput.focus(); - suggestions.classList.remove('d-none'); - } - - if (e.keyCode === 27 ) {//escape - searchinput.blur(); - suggestions.classList.add('d-none'); - closeAllLists(); - } - - const focusableSuggestions= suggestions.querySelectorAll('a'); - if (suggestions.classList.contains('d-none') - || focusableSuggestions.length === 0) { - return; - } - const focusable= [...focusableSuggestions]; - const index = focusable.indexOf(document.activeElement); - - let nextIndex = 0; - - if (e.keyCode === 38) {//up arrow - e.preventDefault(); - nextIndex= index > 0 ? index-1 : 0; - focusableSuggestions[nextIndex].focus(); - } - else if (e.keyCode === 40) {//down arrow - e.preventDefault(); - nextIndex= index+1 < focusable.length ? index+1 : index; - focusableSuggestions[nextIndex].focus(); - } - -} - -// Get substring by bytes -// If using JavaScript inline substring method, it will return error codes -// Source: https://www.52pojie.cn/thread-1059814-1-1.html -function substringByByte(str, maxLength) { - var result = ""; - var flag = false; - var len = 0; - var length = 0; - var length2 = 0; - for (var i = 0; i < str.length; i++) { - var code = str.codePointAt(i).toString(16); - if (code.length > 4) { - i++; - if ((i + 1) < str.length) { - flag = str.codePointAt(i + 1).toString(16) == "200d"; - } - } - if (flag) { - len += getByteByHex(code); - if (i == str.length - 1) { - length += len; - if (length <= maxLength) { - result += str.substr(length2, i - length2 + 1); - } else { - break - } - } - } else { - if (len != 0) { - length += len; - length += getByteByHex(code); - if (length <= maxLength) { - result += str.substr(length2, i - length2 + 1); - length2 = i + 1; - } else { - break - } - len = 0; - continue; - } - length += getByteByHex(code); - if (length <= maxLength) { - if (code.length <= 4) { - result += str[i] - } else { - result += str[i - 1] + str[i] - } - length2 = i + 1; - } else { - break - } - } - } - return result; -} - -// Get the string bytes from binary -function getByteByBinary(binaryCode) { - // Binary system, starts with `0b` in ES6 - // Octal number system, starts with `0` in ES5 and starts with `0o` in ES6 - // Hexadecimal, starts with `0x` in both ES5 and ES6 - var byteLengthDatas = [0, 1, 2, 3, 4]; - var len = byteLengthDatas[Math.ceil(binaryCode.length / 8)]; - return len; -} - -// Get the string bytes from hexadecimal -function getByteByHex(hexCode) { - return getByteByBinary(parseInt(hexCode, 16).toString(2)); -} - -window.onload = function() { - if (document.body.contains(document.goSearch)) { - document.goSearch.onsubmit = function() { return goSearchNow() }; - var suggestions = document.getElementById("suggestions"); - var searchinput = document.getElementById("searchinput"); - document.addEventListener("keydown", inputFocus); - document.addEventListener("click", function(event) {suggestions.contains(event.target) || suggestions.classList.add("d-none")}); - - /* - Source: - - https://github.com/nextapps-de/flexsearch#index-documents-field-search - - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html - - http://elasticlunr.com/ - - https://github.com/getzola/zola/blob/master/docs/static/search.js - - https://github.com/aaranxu/adidoks/blob/main/static/js/search.js - */ - (function(){ - var lang = document.documentElement.getAttribute("lang"); - var langOnly = lang.substring(0, 2); - var baseUrl = document.querySelector("meta[name='base']").getAttribute("content"); - if (baseUrl.slice(-1) == "/") { - baseUrl = baseUrl.slice(0, -1); - } - - var index; - searchinput.addEventListener('input', show_results, true); - suggestions.addEventListener('click', accept_suggestion, true); - - async function show_results(){ - var initIndex = async function () { - if (index === undefined) { - index = fetch(baseUrl + '/search_index.' + langOnly + '.json') - .then( - async function(response) { - return await elasticlunr.Index.load(await response.json()); - } - ); - } - let res = await index; - return res; - } - var value = this.value.trim(); - var options = { - bool: "OR", - fields: { - title: {boost: 2}, - body: {boost: 1}, - } - }; - //var results = index.search(value, options); - var results = (await initIndex()).search(value, options); - - var entry, childs = suggestions.childNodes; - var i = 0, len = results.length; - var items = value.split(/\s+/); - suggestions.classList.remove('d-none'); - - results.forEach(function(page) { - if (page.doc.body !== '') { - entry = document.createElement('div'); - - entry.innerHTML = ''; - - a = entry.querySelector('a'), - t = entry.querySelector('span:first-child'), - d = entry.querySelector('span:nth-child(2)'); - a.href = page.ref; - t.textContent = page.doc.title; - d.innerHTML = makeTeaser(page.doc.body, items); - - suggestions.appendChild(entry); - } - }); - - while(childs.length > len){ - suggestions.removeChild(childs[i]) - } - - } - - function accept_suggestion(){ - - while(suggestions.lastChild){ - - suggestions.removeChild(suggestions.lastChild); - } - - return false; - } - - /* Taken from mdbook - // The strategy is as follows: - // First, assign a value to each word in the document: - // Words that correspond to search terms (stemmer aware): 40 - // Normal words: 2 - // First word in a sentence: 8 - // Then use a sliding window with a constant number of words and count the - // sum of the values of the words within the window. Then use the window that got the - // maximum sum. If there are multiple maximas, then get the last one. - // Enclose the terms in . - */ - function makeTeaser(body, terms) { - var TERM_WEIGHT = 40; - var NORMAL_WORD_WEIGHT = 2; - var FIRST_WORD_WEIGHT = 8; - var TEASER_MAX_WORDS = 30; - - var stemmedTerms = terms.map(function (w) { - return elasticlunr.stemmer(w.toLowerCase()); - }); - var termFound = false; - var index = 0; - var weighted = []; // contains elements of ["word", weight, index_in_document] - - // split in sentences, then words - var sentences = body.toLowerCase().split(". "); - for (var i in sentences) { - var words = sentences[i].split(/[\s\n]/); - var value = FIRST_WORD_WEIGHT; - for (var j in words) { - - var word = words[j]; - - if (word.length > 0) { - for (var k in stemmedTerms) { - if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) { - value = TERM_WEIGHT; - termFound = true; - } - } - weighted.push([word, value, index]); - value = NORMAL_WORD_WEIGHT; - } - - index += word.length; - index += 1; // ' ' or '.' if last word in sentence - } - - index += 1; // because we split at a two-char boundary '. ' - } - - if (weighted.length === 0) { - if (body.length !== undefined && body.length > TEASER_MAX_WORDS * 10) { - return body.substring(0, TEASER_MAX_WORDS * 10) + '...'; - } else { - return body; - } - } - - var windowWeights = []; - var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS); - // We add a window with all the weights first - var curSum = 0; - for (var i = 0; i < windowSize; i++) { - curSum += weighted[i][1]; - } - windowWeights.push(curSum); - - for (var i = 0; i < weighted.length - windowSize; i++) { - curSum -= weighted[i][1]; - curSum += weighted[i + windowSize][1]; - windowWeights.push(curSum); - } - - // If we didn't find the term, just pick the first window - var maxSumIndex = 0; - if (termFound) { - var maxFound = 0; - // backwards - for (var i = windowWeights.length - 1; i >= 0; i--) { - if (windowWeights[i] > maxFound) { - maxFound = windowWeights[i]; - maxSumIndex = i; - } - } - } - - var teaser = []; - var startIndex = weighted[maxSumIndex][2]; - for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) { - var word = weighted[i]; - if (startIndex < word[2]) { - // missing text from index to start of `word` - teaser.push(body.substring(startIndex, word[2])); - startIndex = word[2]; - } - - // add around search terms - if (word[1] === TERM_WEIGHT) { - teaser.push(""); - } - - startIndex = word[2] + word[0].length; - // Check the string is ascii characters or not - var re = /^[\x00-\xff]+$/ - if (word[1] !== TERM_WEIGHT && word[0].length >= 12 && !re.test(word[0])) { - // If the string's length is too long, it maybe a Chinese/Japance/Korean article - // if using substring method directly, it may occur error codes on emoji chars - var strBefor = body.substring(word[2], startIndex); - var strAfter = substringByByte(strBefor, 12); - teaser.push(strAfter); - } else { - teaser.push(body.substring(word[2], startIndex)); - } - - if (word[1] === TERM_WEIGHT) { - teaser.push(""); - } - } - teaser.push("…"); - return teaser.join(""); - } - document.goSearch.onsubmit = function() { return goSearchNow() }; - }()); - } -}; - - - - -- cgit v1.3.1