139 lines
3.6 KiB
JavaScript
139 lines
3.6 KiB
JavaScript
const skippedCategories = ["manual"];
|
|
|
|
class Node {
|
|
constructor(name, element, expandable, noAutoCollapse, children = []) {
|
|
this.name = name;
|
|
this.element = element;
|
|
this.expandable = expandable;
|
|
this.noAutoCollapse = noAutoCollapse;
|
|
this.children = children;
|
|
}
|
|
|
|
AddChild(name, element, expandable, noAutoCollapse, children) {
|
|
let newNode = new Node(name, element, expandable, noAutoCollapse, children);
|
|
this.children.push(newNode);
|
|
|
|
return newNode;
|
|
}
|
|
}
|
|
|
|
class SearchManager {
|
|
constructor(input, contents) {
|
|
this.input = input;
|
|
this.input.addEventListener("input", event => {
|
|
this.OnInputUpdated(this.input.value.toLowerCase().replace(/:/g, "."));
|
|
});
|
|
|
|
// setup search tree
|
|
this.tree = new Node("", document.createElement("null"), true, true);
|
|
this.entries = {};
|
|
|
|
const categoryElements = contents.querySelectorAll(".category");
|
|
|
|
// iterate each kind (hooks/libraries/classes/etc)
|
|
for (const category of categoryElements) {
|
|
const nameElement = category.querySelector(":scope > summary > h2");
|
|
|
|
if (!nameElement) {
|
|
continue;
|
|
}
|
|
|
|
const categoryName = nameElement.textContent.trim().toLowerCase();
|
|
|
|
if (skippedCategories.includes(categoryName)) {
|
|
continue;
|
|
}
|
|
|
|
let categoryNode = this.tree.AddChild(categoryName, category, true, true);
|
|
const sectionElements = category.querySelectorAll(":scope > ul > li");
|
|
|
|
for (const section of sectionElements) {
|
|
const entryElements = section.querySelectorAll(":scope > details > ul > li > a");
|
|
const sectionName = section.querySelector(":scope > details > summary > a")
|
|
.textContent
|
|
.trim()
|
|
.toLowerCase();
|
|
|
|
let sectionNode = categoryNode.AddChild(sectionName, section.querySelector(":scope > details"), true);
|
|
|
|
for (let i = 0; i < entryElements.length; i++) {
|
|
const entryElement = entryElements[i];
|
|
const entryName = entryElement.textContent.trim().toLowerCase();
|
|
|
|
sectionNode.AddChild(sectionName + "." + entryName, entryElement.parentElement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ResetVisibility(current) {
|
|
current.element.style.display = "";
|
|
|
|
if (current.noAutoCollapse) {
|
|
current.element.open = true;
|
|
}
|
|
else if (current.expandable) {
|
|
current.element.open = false;
|
|
}
|
|
|
|
for (let node of current.children) {
|
|
this.ResetVisibility(node);
|
|
}
|
|
}
|
|
|
|
Search(input, current) {
|
|
let matched = false;
|
|
|
|
if (current.name.indexOf(input) != -1) {
|
|
matched = true;
|
|
}
|
|
|
|
for (let node of current.children) {
|
|
let childMatched = this.Search(input, node);
|
|
matched = matched || childMatched;
|
|
}
|
|
|
|
if (matched) {
|
|
current.element.style.display = "";
|
|
|
|
if (current.expandable) {
|
|
current.element.open = true;
|
|
}
|
|
} else {
|
|
current.element.style.display = "none";
|
|
|
|
if (current.expandable) {
|
|
current.element.open = false;
|
|
}
|
|
}
|
|
|
|
return matched;
|
|
}
|
|
|
|
OnInputUpdated(input) {
|
|
if (input.length <= 1) {
|
|
this.ResetVisibility(this.tree);
|
|
return;
|
|
}
|
|
|
|
this.Search(input, this.tree);
|
|
}
|
|
}
|
|
|
|
window.onload = function() {
|
|
const openDetails = document.querySelector(".category > ul > li > details[open]");
|
|
|
|
if (openDetails) {
|
|
openDetails.scrollIntoView();
|
|
}
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const searchInput = document.getElementById("search");
|
|
const contents = document.querySelector("body > main > nav > section");
|
|
|
|
if (searchInput && contents) {
|
|
new SearchManager(searchInput, contents);
|
|
}
|
|
});
|