-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
10500ed
commit 0ade950
Showing
8 changed files
with
310 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
.search-container { | ||
position: absolute; | ||
font-size: 12px; | ||
top: 20px; | ||
left: 20px; | ||
width: 320px; | ||
z-index: 2; | ||
input { | ||
border: 1px solid darken($white, 42); | ||
padding: 0.5rem; | ||
width: 100%; | ||
} | ||
} | ||
|
||
#search-nav { | ||
display: none; | ||
} | ||
|
||
.search-results { | ||
display: none; | ||
top: 40px; | ||
position: absolute; | ||
background-color: $white; | ||
padding: 1rem; | ||
max-height: 500px; | ||
width: 150%; | ||
overflow-y: auto; | ||
border: 2px solid; | ||
box-shadow: 3px 3px 3px 2px rgba(0, 0, 0, 0.1); | ||
&__items { | ||
list-style: none; | ||
padding: 1rem; | ||
z-index: 3; | ||
} | ||
li { | ||
margin-top: 1rem; | ||
border-bottom: 1px solid #ccc; | ||
&:first-of-type { | ||
margin-top: 0; | ||
} | ||
} | ||
&__item { | ||
margin-bottom: 1rem; | ||
a { | ||
font-size: 1.2rem; | ||
display: inline-block; | ||
margin-bottom: 0.5rem; | ||
-webkit-text-decoration-line: underline; | ||
text-decoration-line: underline; | ||
-webkit-text-decoration-style: dashed; | ||
text-decoration-style: dashed; | ||
text-decoration-color: $green; | ||
text-decoration-thickness: 2px; | ||
} | ||
} | ||
} | ||
|
||
@media screen and (max-width: 640px) { | ||
.search-container { | ||
top: 70px; | ||
left: 50%; | ||
right: unset; | ||
margin-right: -50%; | ||
transform: translate(-50%, 0); | ||
} | ||
.search-results { | ||
left: 50%; | ||
right: unset; | ||
margin-right: -50%; | ||
transform: translate(-50%, 0); | ||
} | ||
} | ||
|
||
@media (prefers-color-scheme: dark) { | ||
.search-container { | ||
input { | ||
color: $white; | ||
border-color: darken($white, 30); | ||
background-color: $dark-blue; | ||
} | ||
} | ||
.search-results { | ||
background-color: $dark-blue; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
document.getElementById('search-nav').style.display='block'; | ||
|
||
function debounce(func, wait) { | ||
var timeout; | ||
|
||
return function () { | ||
var context = this; | ||
var args = arguments; | ||
|
||
clearTimeout(timeout); | ||
timeout = setTimeout(function () { | ||
timeout = null; | ||
func.apply(context, args); | ||
}, wait); | ||
}; | ||
} | ||
|
||
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 = []; | ||
var sentences = body.toLowerCase().split(". "); | ||
|
||
for (var i in sentences) { | ||
var words = sentences[i].split(" "); | ||
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; | ||
} | ||
|
||
index += 1; | ||
} | ||
|
||
if (weighted.length === 0) { | ||
return body; | ||
} | ||
|
||
var windowWeights = []; | ||
var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS); | ||
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); | ||
} | ||
|
||
var maxSumIndex = 0; | ||
|
||
if (termFound) { | ||
var maxFound = 0; | ||
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]) { | ||
teaser.push(body.substring(startIndex, word[2])); | ||
startIndex = word[2]; | ||
} | ||
|
||
if (word[1] === TERM_WEIGHT) { | ||
teaser.push("<b>"); | ||
} | ||
startIndex = word[2] + word[0].length; | ||
teaser.push(body.substring(word[2], startIndex)); | ||
|
||
if (word[1] === TERM_WEIGHT) { | ||
teaser.push("</b>"); | ||
} | ||
} | ||
|
||
teaser.push(" …"); | ||
return teaser.join(""); | ||
} | ||
|
||
function formatSearchResultItem(item, terms) { | ||
return '<div class="search-results__item">' | ||
+ `<a href="${item.ref}">${item.doc.title}</a>` | ||
+ `<div>${makeTeaser(item.doc.body, terms)}</div>` | ||
+ '</div>'; | ||
} | ||
|
||
function initSearch() { | ||
var $searchInput = document.getElementById("search"); | ||
var $searchResults = document.querySelector(".search-results"); | ||
var $searchResultsItems = document.querySelector(".search-results__items"); | ||
var MAX_ITEMS = 10; | ||
|
||
var options = { | ||
bool: "AND", | ||
fields: { | ||
title: {boost: 2}, | ||
body: {boost: 1}, | ||
} | ||
}; | ||
|
||
var currentTerm = ""; | ||
var index; | ||
|
||
var initIndex = async function () { | ||
if (index === undefined) { | ||
index = fetch("/search_index.en.json") | ||
.then( | ||
async function(response) { | ||
return await elasticlunr.Index.load(await response.json()); | ||
} | ||
); | ||
} | ||
|
||
let res = await index; | ||
return res; | ||
} | ||
|
||
$searchInput.addEventListener("keyup", debounce(async function() { | ||
var term = $searchInput.value.trim(); | ||
if (term === currentTerm) { | ||
return; | ||
} | ||
|
||
$searchResults.style.display = term === "" ? "none" : "block"; | ||
$searchResultsItems.innerHTML = ""; | ||
currentTerm = term; | ||
|
||
if (term === "") { | ||
return; | ||
} | ||
|
||
var results = (await initIndex()).search(term, options); | ||
if (results.length === 0) { | ||
$searchResults.style.display = "none"; | ||
return; | ||
} | ||
|
||
for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) { | ||
var item = document.createElement("li"); | ||
item.innerHTML = formatSearchResultItem(results[i], term.split(" ")); | ||
$searchResultsItems.appendChild(item); | ||
} | ||
}, 150)); | ||
|
||
window.addEventListener('click', function(e) { | ||
if ($searchResults.style.display == "block" && !$searchResults.contains(e.target)) { | ||
$searchResults.style.display = "none"; | ||
} | ||
}); | ||
} | ||
|
||
|
||
if (document.readyState === "complete" || | ||
(document.readyState !== "loading" && !document.documentElement.doScroll) | ||
) { | ||
initSearch(); | ||
} else { | ||
document.addEventListener("DOMContentLoaded", initSearch); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters