Restructure source tree
This commit is contained in:
parent
f179b0805c
commit
3abfef4528
10 changed files with 173 additions and 130 deletions
|
@ -1,7 +1,7 @@
|
|||
import TabManager from "./TabManager";
|
||||
import sections from "./sections";
|
||||
import TabManager from "./ui/TabManager";
|
||||
import sections from "./ui/sections";
|
||||
import { nextAnimationFrame } from "./utils";
|
||||
import { searchBox } from "./search";
|
||||
import { searchBox } from "./scripts/search";
|
||||
|
||||
// @ts-expect-error: Parcel image import
|
||||
import unknown from "~/assets/images/tab-icons/unknown.svg";
|
||||
|
@ -51,7 +51,7 @@ async function load() {
|
|||
manager.setLoading(false);
|
||||
|
||||
// Set first page as active
|
||||
manager.setActive("Guide_to_chemistry");
|
||||
manager.setActive("Infections");
|
||||
});
|
||||
}
|
||||
if ("serviceWorker" in navigator) {
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import { darken, ColorFmt, lighten } from "./darkmode";
|
||||
import { registerSearchEntries } from "./search";
|
||||
import { findParent } from "./utils";
|
||||
import chemistryScript from "./pages/chemistry";
|
||||
|
||||
// This is used for cache busting when userscript changes significantly.
|
||||
// Only change it when you made changes to the processHTML part!
|
||||
export const CURRENT_VERSION = "bb7abd544a19369d4b6b7e3dde3eb3cc34c023d4";
|
||||
|
||||
const MAX_WIDTH = 440;
|
||||
|
||||
function chemistryFixups(root: HTMLElement) {
|
||||
// Fix inconsistencies with <p> on random parts
|
||||
// Ideally I'd like a <p> or something on every part, wrapping it completely, but for now let's just kill 'em
|
||||
|
@ -246,115 +249,35 @@ export function processHTML(root: HTMLElement, docname: string): void {
|
|||
}
|
||||
}
|
||||
|
||||
function chemistryScript(root: HTMLElement) {
|
||||
// Add event to autofill child checkboxes
|
||||
root
|
||||
.querySelectorAll(".bgus_part_tooltip > .bgus_checkbox")
|
||||
.forEach((box: HTMLInputElement) => {
|
||||
const tooltip = box.parentElement.nextElementSibling;
|
||||
box.addEventListener("click", () => {
|
||||
tooltip
|
||||
.querySelectorAll(".bgus_checkbox")
|
||||
.forEach((el: HTMLInputElement) => {
|
||||
el.checked = box.checked;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Add event to collapse subsections
|
||||
root.querySelectorAll(".bgus_nested_element").forEach((twistie) => {
|
||||
twistie.addEventListener("click", () => {
|
||||
twistie.classList.toggle("bgus_collapsed");
|
||||
});
|
||||
});
|
||||
|
||||
const setPartSize = (labels, ml) => {
|
||||
labels.forEach((el) => {
|
||||
const part = el.parentElement.dataset.amount;
|
||||
const total = el.parentElement.parentElement.dataset.parts;
|
||||
const amt = Math.ceil(ml * (part / total));
|
||||
el.innerHTML = `${amt} ml`;
|
||||
// Lookup tooltips
|
||||
let next = el.parentElement.nextElementSibling;
|
||||
while (next) {
|
||||
if (next.classList.contains("tooltip")) {
|
||||
const sublabels = [];
|
||||
next.querySelector(".tooltiptext").childNodes.forEach((ch) => {
|
||||
if (ch.classList && ch.classList.contains("bgus_part")) {
|
||||
sublabels.push(ch.querySelector(".bgus_part_label"));
|
||||
}
|
||||
});
|
||||
setPartSize(sublabels, amt);
|
||||
}
|
||||
if (next.classList.contains("bgus_part")) {
|
||||
// Done searching
|
||||
break;
|
||||
}
|
||||
next = next.nextElementSibling;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Init fuzzy search with elements
|
||||
const el = Array.from(
|
||||
root.querySelectorAll<HTMLElement>(
|
||||
"table.wikitable > tbody > tr:not(:first-child) > th"
|
||||
)
|
||||
);
|
||||
registerSearchEntries(
|
||||
el.map((element, id) => ({
|
||||
page: "Guide_to_chemistry",
|
||||
name: element
|
||||
.querySelector(".reagent-header")
|
||||
.textContent.trim()
|
||||
.replace("▮", ""),
|
||||
element,
|
||||
alignment: "center",
|
||||
id,
|
||||
}))
|
||||
);
|
||||
|
||||
document.body.addEventListener("keydown", (ev) => {
|
||||
if (ev.shiftKey) {
|
||||
switch (ev.keyCode) {
|
||||
// SHIFT+C = Toggle checkboxes
|
||||
case 67: {
|
||||
root.classList.toggle("bgus_cbox");
|
||||
root
|
||||
.querySelectorAll(".bgus_checkbox:checked")
|
||||
.forEach((sel: HTMLInputElement) => {
|
||||
sel.checked = false;
|
||||
});
|
||||
break;
|
||||
function virologyScript(root: HTMLElement): void {
|
||||
const symptoms = document.querySelector("#Symptoms_Table .wikitable");
|
||||
//parseTable(symptoms);
|
||||
}
|
||||
|
||||
// SHIFT+B = Set whole size (beaker?) for parts/units
|
||||
case 66: {
|
||||
const size = parseInt(
|
||||
prompt("Write target ml (0 to reset)", "90"),
|
||||
10
|
||||
);
|
||||
if (Number.isNaN(size) || size <= 0) {
|
||||
// Reset to parts/unit
|
||||
root
|
||||
.querySelectorAll(".bgus_part_label")
|
||||
.forEach((sel: HTMLElement) => {
|
||||
sel.innerHTML = sel.dataset.src;
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function postProcessHTML(root: HTMLElement, docname: string): void {
|
||||
// This should be noop unless we're testing changes before committing them to processHTML
|
||||
document.querySelectorAll("img[width]").forEach((img) => {
|
||||
const width = img.getAttribute("width");
|
||||
|
||||
// Don't care if they are not absolutely sized
|
||||
if (width.includes("%")) {
|
||||
return;
|
||||
}
|
||||
setPartSize(
|
||||
root.querySelectorAll("td > .bgus_part > .bgus_part_label"),
|
||||
+size
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
const widthI = parseInt(width, 10);
|
||||
if (widthI > MAX_WIDTH) {
|
||||
img.setAttribute("width", "100%");
|
||||
img.removeAttribute("height"); // Remove any height so we don't have to deal with the crazy math
|
||||
}
|
||||
});
|
||||
|
||||
switch (docname) {
|
||||
case "Infections":
|
||||
virologyScript(root);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
function genericScript(root: HTMLElement, docname: string) {
|
||||
|
@ -387,6 +310,7 @@ export function bindFunctions(root: HTMLElement, docname: string): void {
|
|||
|
||||
export default {
|
||||
CURRENT_VERSION,
|
||||
postProcessHTML,
|
||||
processHTML,
|
||||
bindFunctions,
|
||||
};
|
112
src/scripts/pages/chemistry.ts
Normal file
112
src/scripts/pages/chemistry.ts
Normal file
|
@ -0,0 +1,112 @@
|
|||
import { registerSearchEntries } from "../search";
|
||||
|
||||
export default function chemistryScript(root: HTMLElement): void {
|
||||
// Add event to autofill child checkboxes
|
||||
root
|
||||
.querySelectorAll(".bgus_part_tooltip > .bgus_checkbox")
|
||||
.forEach((box: HTMLInputElement) => {
|
||||
const tooltip = box.parentElement.nextElementSibling;
|
||||
box.addEventListener("click", () => {
|
||||
tooltip
|
||||
.querySelectorAll(".bgus_checkbox")
|
||||
.forEach((el: HTMLInputElement) => {
|
||||
el.checked = box.checked;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Add event to collapse subsections
|
||||
root.querySelectorAll(".bgus_nested_element").forEach((twistie) => {
|
||||
twistie.addEventListener("click", () => {
|
||||
twistie.classList.toggle("bgus_collapsed");
|
||||
});
|
||||
});
|
||||
|
||||
const setPartSize = (labels, ml) => {
|
||||
labels.forEach((el) => {
|
||||
const part = el.parentElement.dataset.amount;
|
||||
const total = el.parentElement.parentElement.dataset.parts;
|
||||
const amt = Math.ceil(ml * (part / total));
|
||||
el.innerHTML = `${amt} ml`;
|
||||
// Lookup tooltips
|
||||
let next = el.parentElement.nextElementSibling;
|
||||
while (next) {
|
||||
if (next.classList.contains("tooltip")) {
|
||||
const sublabels = [];
|
||||
next.querySelector(".tooltiptext").childNodes.forEach((ch) => {
|
||||
if (ch.classList && ch.classList.contains("bgus_part")) {
|
||||
sublabels.push(ch.querySelector(".bgus_part_label"));
|
||||
}
|
||||
});
|
||||
setPartSize(sublabels, amt);
|
||||
}
|
||||
if (next.classList.contains("bgus_part")) {
|
||||
// Done searching
|
||||
break;
|
||||
}
|
||||
next = next.nextElementSibling;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Init fuzzy search with elements
|
||||
const el = Array.from(
|
||||
root.querySelectorAll<HTMLElement>(
|
||||
"table.wikitable > tbody > tr:not(:first-child) > th"
|
||||
)
|
||||
);
|
||||
registerSearchEntries(
|
||||
el.map((element, id) => ({
|
||||
page: "Guide_to_chemistry",
|
||||
name: element
|
||||
.querySelector(".reagent-header")
|
||||
.textContent.trim()
|
||||
.replace("▮", ""),
|
||||
element,
|
||||
alignment: "center",
|
||||
id,
|
||||
}))
|
||||
);
|
||||
|
||||
document.body.addEventListener("keydown", (ev) => {
|
||||
if (ev.shiftKey) {
|
||||
switch (ev.keyCode) {
|
||||
// SHIFT+C = Toggle checkboxes
|
||||
case 67: {
|
||||
root.classList.toggle("bgus_cbox");
|
||||
root
|
||||
.querySelectorAll(".bgus_checkbox:checked")
|
||||
.forEach((sel: HTMLInputElement) => {
|
||||
sel.checked = false;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
// SHIFT+B = Set whole size (beaker?) for parts/units
|
||||
case 66: {
|
||||
const size = parseInt(
|
||||
prompt("Write target ml (0 to reset)", "90"),
|
||||
10
|
||||
);
|
||||
if (Number.isNaN(size) || size <= 0) {
|
||||
// Reset to parts/unit
|
||||
root
|
||||
.querySelectorAll(".bgus_part_label")
|
||||
.forEach((sel: HTMLElement) => {
|
||||
sel.innerHTML = sel.dataset.src;
|
||||
});
|
||||
return;
|
||||
}
|
||||
setPartSize(
|
||||
root.querySelectorAll("td > .bgus_part > .bgus_part_label"),
|
||||
+size
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
0
src/scripts/pages/virology.ts
Normal file
0
src/scripts/pages/virology.ts
Normal file
|
@ -1,5 +1,5 @@
|
|||
import { nextAnimationFrame } from "./utils";
|
||||
import TabManager from "./TabManager";
|
||||
import { nextAnimationFrame } from "../utils";
|
||||
import TabManager from "../ui/TabManager";
|
||||
|
||||
interface SearchEntry {
|
||||
page: string;
|
15
src/scripts/utils.ts
Normal file
15
src/scripts/utils.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
export function findParent(
|
||||
base: HTMLElement,
|
||||
matchFn: (candidate: HTMLElement) => boolean
|
||||
): HTMLElement | null {
|
||||
let parent = base.parentElement;
|
||||
while (parent != null) {
|
||||
if (matchFn(parent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
export default { findParent };
|
|
@ -1,10 +1,14 @@
|
|||
// @ts-expect-error: Asset imports are handled by parcel
|
||||
import speen from "~/assets/images/speen.svg";
|
||||
import { getPageHTML } from "./wiki";
|
||||
import { processHTML, bindFunctions, CURRENT_VERSION } from "./userscript";
|
||||
import cache from "./cache";
|
||||
import { nextAnimationFrame, delay } from "./utils";
|
||||
import { TabInfo } from "./sections";
|
||||
import { getPageHTML } from "../wiki";
|
||||
import {
|
||||
processHTML,
|
||||
bindFunctions,
|
||||
CURRENT_VERSION,
|
||||
postProcessHTML,
|
||||
} from "../scripts/index";
|
||||
import cache from "../cache";
|
||||
import { nextAnimationFrame, delay } from "../utils";
|
||||
|
||||
// @ts-expect-error: Parcel image import
|
||||
import unknown from "~/assets/images/tab-icons/unknown.svg";
|
||||
|
@ -76,6 +80,8 @@ async function loadPage(page: string, elem: HTMLElement): Promise<HTMLElement> {
|
|||
} else {
|
||||
// Set cached content as HTML
|
||||
elem.innerHTML = html;
|
||||
|
||||
postProcessHTML(elem, page); // noop in prod, used in dev for testing candidate DOM changes
|
||||
}
|
||||
|
||||
bindFunctions(elem, page);
|
16
src/utils.ts
16
src/utils.ts
|
@ -1,17 +1,3 @@
|
|||
export function findParent(
|
||||
base: HTMLElement,
|
||||
matchFn: (candidate: HTMLElement) => boolean
|
||||
): HTMLElement | null {
|
||||
let parent = base.parentElement;
|
||||
while (parent != null) {
|
||||
if (matchFn(parent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
export function nextAnimationFrame(): Promise<void> {
|
||||
return new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
||||
}
|
||||
|
@ -22,4 +8,4 @@ export function delay(ms: number): Promise<void> {
|
|||
});
|
||||
}
|
||||
|
||||
export default { findParent, nextAnimationFrame, delay };
|
||||
export default { nextAnimationFrame, delay };
|
||||
|
|
Reference in a new issue