215 lines
8.0 KiB
JavaScript
215 lines
8.0 KiB
JavaScript
"use strict";
|
|
|
|
const assetV = (document.querySelector('meta[name="aego-assets"]') || {}).content || "";
|
|
|
|
(function () {
|
|
const root = document.querySelector('meta[name="aego-root"]').content;
|
|
const input = document.getElementById("search");
|
|
const results = document.getElementById("results");
|
|
const NAV_KEY = "aego.docs.groups";
|
|
const SECTIONS = { start: "Getting started", guides: "Guides", reference: "Reference" };
|
|
const RANK = { start: 0, guides: 1, reference: 2 };
|
|
let index = null;
|
|
let active = 0;
|
|
let shown = [];
|
|
|
|
document.querySelector(".menu").addEventListener("click", () => document.body.classList.toggle("nav-open"));
|
|
|
|
function loadState() {
|
|
try {
|
|
return JSON.parse(localStorage.getItem(NAV_KEY)) || {};
|
|
} catch (_) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
const state = loadState();
|
|
for (const d of document.querySelectorAll(".side details.group")) {
|
|
const id = d.dataset.group;
|
|
if (d.dataset.current) d.open = true;
|
|
else if (id in state) d.open = !!state[id];
|
|
else d.open = id === "start";
|
|
d.addEventListener("toggle", () => {
|
|
state[id] = d.open;
|
|
try {
|
|
localStorage.setItem(NAV_KEY, JSON.stringify(state));
|
|
} catch (_) {}
|
|
});
|
|
}
|
|
const side = document.querySelector(".side");
|
|
const current = document.querySelector(".side a.current");
|
|
if (side && current) {
|
|
const top = current.getBoundingClientRect().top - side.getBoundingClientRect().top + side.scrollTop;
|
|
side.scrollTop = Math.max(0, top - side.clientHeight / 2);
|
|
}
|
|
|
|
for (const pre of document.querySelectorAll(".doc pre")) {
|
|
const code = pre.querySelector("code");
|
|
if (!code || pre.classList.contains("sig")) continue;
|
|
const btn = document.createElement("button");
|
|
btn.type = "button";
|
|
btn.className = "copy";
|
|
btn.textContent = "Copy";
|
|
btn.addEventListener("click", async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(code.textContent);
|
|
btn.textContent = "Copied";
|
|
} catch (_) {
|
|
btn.textContent = "Blocked";
|
|
}
|
|
setTimeout(() => (btn.textContent = "Copy"), 1200);
|
|
});
|
|
pre.appendChild(btn);
|
|
}
|
|
|
|
const tocLinks = [...document.querySelectorAll(".toc a")];
|
|
if (tocLinks.length && "IntersectionObserver" in window) {
|
|
const byId = new Map(tocLinks.map((a) => [decodeURIComponent(a.hash.slice(1)), a]));
|
|
const obs = new IntersectionObserver(
|
|
(entries) => {
|
|
for (const e of entries) {
|
|
if (!e.isIntersecting) continue;
|
|
const a = byId.get(e.target.id);
|
|
if (!a) continue;
|
|
for (const x of tocLinks) x.classList.toggle("active", x === a);
|
|
}
|
|
},
|
|
{ rootMargin: "-60px 0px -70% 0px" },
|
|
);
|
|
for (const id of byId.keys()) {
|
|
const el = document.getElementById(id);
|
|
if (el) obs.observe(el);
|
|
}
|
|
}
|
|
|
|
function score(item, q) {
|
|
const t = item.t.toLowerCase();
|
|
const id = item.i.toLowerCase();
|
|
if (t === q) return 1000;
|
|
if (t.startsWith(q)) return 800 - t.length;
|
|
const at = t.indexOf(q);
|
|
if (at >= 0) return 600 - at;
|
|
const ai = id.indexOf(q);
|
|
if (ai >= 0) return 400 - ai;
|
|
let j = 0;
|
|
for (let i = 0; i < t.length && j < q.length; i++) if (t[i] === q[j]) j++;
|
|
return j === q.length ? 100 : 0;
|
|
}
|
|
|
|
function escapeHTML(s) {
|
|
return s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
}
|
|
|
|
function render(items) {
|
|
let html = "";
|
|
let last = null;
|
|
items.forEach((it, i) => {
|
|
if (it.c !== last) {
|
|
html += `<li class="cat">${escapeHTML(SECTIONS[it.c] || "Other")}</li>`;
|
|
last = it.c;
|
|
}
|
|
const ic = it.ic ? `<svg width="16" height="16" class="ic" aria-hidden="true"><use href="${root}assets/icons.svg?v=${assetV}#${it.ic}"/></svg>` : "<span></span>";
|
|
html += `<li${i === active ? ' class="active"' : ""}><a href="${root}${it.u}">${ic}<span>${escapeHTML(it.t)}</span><span class="kind">${escapeHTML(it.g || it.k)}</span>${it.s ? `<span class="summary">${escapeHTML(it.s)}</span>` : ""}</a></li>`;
|
|
});
|
|
results.innerHTML = html;
|
|
results.hidden = items.length === 0;
|
|
}
|
|
|
|
async function search() {
|
|
const q = input.value.trim().toLowerCase();
|
|
if (!q) {
|
|
results.hidden = true;
|
|
return;
|
|
}
|
|
if (!index) index = await (await fetch(root + "search.json")).json();
|
|
const top = index
|
|
.map((it) => [score(it, q), it])
|
|
.filter((p) => p[0] > 0)
|
|
.sort((a, b) => b[0] - a[0] || a[1].t.length - b[1].t.length)
|
|
.slice(0, 30)
|
|
.map((p) => p[1]);
|
|
shown = top.map((it, i) => [it, i]).sort((a, b) => (RANK[a[0].c] ?? 3) - (RANK[b[0].c] ?? 3) || a[1] - b[1]).map((p) => p[0]);
|
|
active = 0;
|
|
render(shown);
|
|
}
|
|
|
|
input.addEventListener("input", search);
|
|
input.addEventListener("keydown", (e) => {
|
|
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
e.preventDefault();
|
|
active = Math.max(0, Math.min(shown.length - 1, active + (e.key === "ArrowDown" ? 1 : -1)));
|
|
render(shown);
|
|
} else if (e.key === "Enter" && shown[active]) {
|
|
location.href = root + shown[active].u;
|
|
} else if (e.key === "Escape") {
|
|
results.hidden = true;
|
|
input.blur();
|
|
}
|
|
});
|
|
document.addEventListener("keydown", (e) => {
|
|
if (e.key === "/" && document.activeElement !== input && !/INPUT|TEXTAREA/.test(document.activeElement.tagName)) {
|
|
e.preventDefault();
|
|
input.focus();
|
|
}
|
|
});
|
|
document.addEventListener("click", (e) => {
|
|
if (!e.target.closest(".search")) results.hidden = true;
|
|
});
|
|
})();
|
|
|
|
(function () {
|
|
const demo = document.querySelector(".demo[data-src]");
|
|
if (!demo) return;
|
|
const play = () => {
|
|
if (demo.querySelector("iframe")) return;
|
|
const f = document.createElement("iframe");
|
|
f.src = demo.dataset.src;
|
|
f.title = "Aego demo";
|
|
f.allow = "fullscreen; gamepad; autoplay";
|
|
demo.textContent = "";
|
|
demo.appendChild(f);
|
|
f.addEventListener("load", () => f.focus());
|
|
};
|
|
const KEY = "aego-demo-played";
|
|
demo.querySelector(".demo-play").addEventListener("click", () => {
|
|
try {
|
|
localStorage.setItem(KEY, "1");
|
|
} catch (_) {}
|
|
play();
|
|
});
|
|
try {
|
|
if (localStorage.getItem(KEY)) play();
|
|
} catch (_) {}
|
|
})();
|
|
|
|
(function () {
|
|
const input = document.querySelector(".member-filter input");
|
|
if (!input) return;
|
|
const items = [...document.querySelectorAll("table.api tr[data-name], section.member[data-name]")];
|
|
input.addEventListener("input", () => {
|
|
const q = input.value.trim().toLowerCase();
|
|
for (const el of items) el.classList.toggle("hidden-by-filter", q !== "" && !el.dataset.name.includes(q));
|
|
});
|
|
})();
|
|
|
|
(function () {
|
|
const done = new Set();
|
|
const prefetch = (href) => {
|
|
if (!href || done.has(href)) return;
|
|
done.add(href);
|
|
const l = document.createElement("link");
|
|
l.rel = "prefetch";
|
|
l.href = href;
|
|
document.head.appendChild(l);
|
|
};
|
|
const next = document.querySelector(".pager a.next");
|
|
if (next) prefetch(next.href);
|
|
const local = (a) => a && a.origin === location.origin && a.pathname !== location.pathname && /\.html$|\/$/.test(a.pathname);
|
|
const hover = (e) => {
|
|
const a = e.target.closest && e.target.closest("a[href]");
|
|
if (local(a)) prefetch(a.href.split("#")[0]);
|
|
};
|
|
document.addEventListener("pointerover", hover, { passive: true });
|
|
document.addEventListener("focusin", hover);
|
|
})();
|