Skip to content

Commit 3ee264f

Browse files
authored
Create fastsearch.js
1 parent 9010705 commit 3ee264f

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

assets/js/fastsearch.js

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import * as params from '@params';
2+
3+
var fuse; // holds our search engine
4+
var resList = document.getElementById('searchResults');
5+
var sInput = document.getElementById('searchInput');
6+
var first, last, current_elem = null
7+
var resultsAvailable = false;
8+
9+
// load our search index
10+
window.onload = function () {
11+
var xhr = new XMLHttpRequest();
12+
xhr.onreadystatechange = function () {
13+
if (xhr.readyState === 4) {
14+
if (xhr.status === 200) {
15+
var data = JSON.parse(xhr.responseText);
16+
if (data) {
17+
// fuse.js options; check fuse.js website for details
18+
var options = {
19+
distance: 100,
20+
threshold: 0.4,
21+
ignoreLocation: true,
22+
keys: [
23+
'title',
24+
'permalink',
25+
'summary',
26+
'content'
27+
]
28+
};
29+
if (params.fuseOpts) {
30+
options = {
31+
isCaseSensitive: params.fuseOpts.iscasesensitive ? params.fuseOpts.iscasesensitive : false,
32+
includeScore: params.fuseOpts.includescore ? params.fuseOpts.includescore : false,
33+
includeMatches: params.fuseOpts.includematches ? params.fuseOpts.includematches : false,
34+
minMatchCharLength: params.fuseOpts.minmatchcharlength ? params.fuseOpts.minmatchcharlength : 1,
35+
shouldSort: params.fuseOpts.shouldsort ? params.fuseOpts.shouldsort : true,
36+
findAllMatches: params.fuseOpts.findallmatches ? params.fuseOpts.findallmatches : false,
37+
keys: params.fuseOpts.keys ? params.fuseOpts.keys : ['title', 'permalink', 'summary', 'content'],
38+
location: params.fuseOpts.location ? params.fuseOpts.location : 0,
39+
threshold: params.fuseOpts.threshold ? params.fuseOpts.threshold : 0.4,
40+
distance: params.fuseOpts.distance ? params.fuseOpts.distance : 100,
41+
ignoreLocation: params.fuseOpts.ignorelocation ? params.fuseOpts.ignorelocation : true
42+
}
43+
}
44+
fuse = new Fuse(data, options); // build the index from the json file
45+
}
46+
} else {
47+
console.log(xhr.responseText);
48+
}
49+
}
50+
};
51+
xhr.open('GET', "../search.json");
52+
xhr.send();
53+
}
54+
55+
function activeToggle(ae) {
56+
document.querySelectorAll('.focus').forEach(function (element) {
57+
// rm focus class
58+
element.classList.remove("focus")
59+
});
60+
if (ae) {
61+
ae.focus()
62+
document.activeElement = current_elem = ae;
63+
ae.parentElement.classList.add("focus")
64+
} else {
65+
document.activeElement.parentElement.classList.add("focus")
66+
}
67+
}
68+
69+
function reset() {
70+
resultsAvailable = false;
71+
resList.innerHTML = sInput.value = ''; // clear inputbox and searchResults
72+
sInput.focus(); // shift focus to input box
73+
}
74+
75+
// execute search as each character is typed
76+
sInput.onkeyup = function (e) {
77+
// run a search query (for "term") every time a letter is typed
78+
// in the search box
79+
if (fuse) {
80+
const results = fuse.search(this.value.trim()); // the actual query being run using fuse.js
81+
if (results.length !== 0) {
82+
// build our html if result exists
83+
let resultSet = ''; // our results bucket
84+
85+
for (let item in results) {
86+
resultSet += `<li class="post-entry"><header class="entry-header">${results[item].item.title}&nbsp;»</header>` +
87+
`<a href="${results[item].item.permalink}" aria-label="${results[item].item.title}"></a></li>`
88+
}
89+
90+
resList.innerHTML = resultSet;
91+
resultsAvailable = true;
92+
first = resList.firstChild;
93+
last = resList.lastChild;
94+
} else {
95+
resultsAvailable = false;
96+
resList.innerHTML = '';
97+
}
98+
}
99+
}
100+
101+
sInput.addEventListener('search', function (e) {
102+
// clicked on x
103+
if (!this.value) reset()
104+
})
105+
106+
// kb bindings
107+
document.onkeydown = function (e) {
108+
let key = e.key;
109+
var ae = document.activeElement;
110+
111+
let inbox = document.getElementById("searchbox").contains(ae)
112+
113+
if (ae === sInput) {
114+
var elements = document.getElementsByClassName('focus');
115+
while (elements.length > 0) {
116+
elements[0].classList.remove('focus');
117+
}
118+
} else if (current_elem) ae = current_elem;
119+
120+
if (key === "Escape") {
121+
reset()
122+
} else if (!resultsAvailable || !inbox) {
123+
return
124+
} else if (key === "ArrowDown") {
125+
e.preventDefault();
126+
if (ae == sInput) {
127+
// if the currently focused element is the search input, focus the <a> of first <li>
128+
activeToggle(resList.firstChild.lastChild);
129+
} else if (ae.parentElement != last) {
130+
// if the currently focused element's parent is last, do nothing
131+
// otherwise select the next search result
132+
activeToggle(ae.parentElement.nextSibling.lastChild);
133+
}
134+
} else if (key === "ArrowUp") {
135+
e.preventDefault();
136+
if (ae.parentElement == first) {
137+
// if the currently focused element is first item, go to input box
138+
activeToggle(sInput);
139+
} else if (ae != sInput) {
140+
// if the currently focused element is input box, do nothing
141+
// otherwise select the previous search result
142+
activeToggle(ae.parentElement.previousSibling.lastChild);
143+
}
144+
} else if (key === "ArrowRight") {
145+
ae.click(); // click on active link
146+
}
147+
}

0 commit comments

Comments
 (0)