From fcebeda2fddb46d924f4538cd9c0daeb55aa4c9b Mon Sep 17 00:00:00 2001 From: Hamcha Date: Sat, 27 Jun 2020 15:06:14 +0200 Subject: [PATCH] Refactor search/scss and add basic virology fixes --- .eslintrc.js | 1 + src/scripts/index.ts | 9 +- src/scripts/pages/chemistry.ts | 4 +- src/scripts/pages/virology.ts | 49 ++++++- src/scripts/search.ts | 4 +- src/scripts/utils.ts | 74 ++++++++++- style/main.scss | 1 + style/pages/chemistry.scss | 227 +++++++++++++++++---------------- style/pages/virology.scss | 71 +++++++++++ 9 files changed, 322 insertions(+), 118 deletions(-) create mode 100644 style/pages/virology.scss diff --git a/.eslintrc.js b/.eslintrc.js index 5112eb8..e88fad1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,6 +20,7 @@ module.exports = { "no-alert": "off", "no-console": "off", "func-names": "off", + "dot-notation": ["error", { allowPattern: "^[A-Z][a-z]+$" }], "@typescript-eslint/ban-ts-comment": [ "error", { diff --git a/src/scripts/index.ts b/src/scripts/index.ts index bf69117..2b59e4f 100644 --- a/src/scripts/index.ts +++ b/src/scripts/index.ts @@ -1,5 +1,5 @@ import { chemistryScript, processChemistry } from "./pages/chemistry"; -import { virologyScript } from "./pages/virology"; +import { processVirology, virologyScript } from "./pages/virology"; import { genericScript } from "./pages/generic"; import { processGlobal } from "./pages/global"; @@ -40,7 +40,7 @@ export function postProcessHTML(root: HTMLElement, docname: string): void { switch (docname) { case "Infections": - virologyScript(root); + processVirology(root); break; default: } @@ -49,8 +49,13 @@ export function postProcessHTML(root: HTMLElement, docname: string): void { export function bindFunctions(root: HTMLElement, docname: string): void { switch (docname) { case "Guide_to_chemistry": + genericScript(root, docname); chemistryScript(root); break; + case "Infections": + genericScript(root, docname); + virologyScript(root); + break; default: genericScript(root, docname); break; diff --git a/src/scripts/pages/chemistry.ts b/src/scripts/pages/chemistry.ts index fe1d904..4a3d50f 100644 --- a/src/scripts/pages/chemistry.ts +++ b/src/scripts/pages/chemistry.ts @@ -184,14 +184,14 @@ export function chemistryScript(root: HTMLElement): void { // Init fuzzy search with elements const el = Array.from( root.querySelectorAll( - "table.wikitable > tbody > tr:not(:first-child) > th" + "table.wikitable > tbody > tr:not(:first-child)" ) ); registerSearchEntries( el.map((element, id) => ({ page: "Guide_to_chemistry", name: element - .querySelector(".reagent-header") + .querySelector("th .reagent-header") .textContent.trim() .replace("▮", ""), element, diff --git a/src/scripts/pages/virology.ts b/src/scripts/pages/virology.ts index ce54a47..1383216 100644 --- a/src/scripts/pages/virology.ts +++ b/src/scripts/pages/virology.ts @@ -1,8 +1,53 @@ +import { parseTable, makeTable } from "../utils"; +import { registerSearchEntries } from "../search"; + +export function processVirology(root: HTMLElement): void { + const diseaseTable = root.querySelector( + "#Simple_Diseases .wikitable" + ); + const diseases = parseTable(diseaseTable).map((row) => { + const diseaseBlock = document.createElement("td"); + diseaseBlock.innerHTML = ` +
${row["Disease Name"].innerHTML}
+

${row["Vector Name"].innerHTML}

+

${row["Source"].innerHTML}

+

${row["Spread"].innerHTML}

+

${row["Description"].innerHTML}

+ `; + return { + Disease: diseaseBlock, + Cure: row["Cure"], + }; + }); + + const diseaseBetterTable = makeTable(["Disease", "Cure"], diseases); + diseaseBetterTable.className = "disease-ext wikitable"; + diseaseTable.replaceWith(diseaseBetterTable); + + const symptomsTable = root.querySelector( + "#Symptoms_Table .wikitable" + ); + const symptoms = parseTable(symptomsTable); + //symptomsTable.replaceWith(document.createElement("span")); +} + export function virologyScript(root: HTMLElement): void { - const symptoms = document.querySelector("#Symptoms_Table .wikitable"); - //parseTable(symptoms); + // Init fuzzy search with elements + const el = Array.from( + root.querySelectorAll(".disease-ext tr:not(:first-child)") + ); + registerSearchEntries( + el.map((element, id) => ({ + page: "Infections", + name: element.querySelector(".disease-name").textContent.trim(), + element, + alignment: "center", + id, + })) + ); } export default { + processVirology, virologyScript, }; diff --git a/src/scripts/search.ts b/src/scripts/search.ts index bfee9fb..befc367 100644 --- a/src/scripts/search.ts +++ b/src/scripts/search.ts @@ -43,9 +43,9 @@ export function searchBox(): HTMLElement { behavior: "auto", }); document - .querySelectorAll("table.wikitable .bgus_fz_selected") + .querySelectorAll(".bgus_fz_selected") .forEach((sel) => sel.classList.remove("bgus_fz_selected")); - entry.element.parentElement.classList.add("bgus_fz_selected"); + entry.element.classList.add("bgus_fz_selected"); }; const setSelectedResult = (i) => { diff --git a/src/scripts/utils.ts b/src/scripts/utils.ts index c51c129..ceb1110 100644 --- a/src/scripts/utils.ts +++ b/src/scripts/utils.ts @@ -1,3 +1,8 @@ +/** + * Find closest parent that meets a specified condition + * @param base Element to start from + * @param matchFn Matching function, returns true if condition is met + */ export function findParent( base: HTMLElement, matchFn: (candidate: HTMLElement) => boolean @@ -12,4 +17,71 @@ export function findParent( return parent; } -export default { findParent }; +export type TableRowData = Record; +export type TableData = TableRowData[]; + +/** + * Parse a HTML table and return a dictionary of rows as dictionaries + * @param table Table element or any element from where you can query for "th" etc. + */ +export function parseTable(table: HTMLElement): TableData { + const [headerRow, ...valueRows] = Array.from(table.querySelectorAll("tr")); + const headers = Array.from( + headerRow.querySelectorAll("th") + ).map((th) => th.textContent.trim()); + return valueRows.map((tr) => { + const obj = {}; + tr.querySelectorAll("td,th").forEach((val, i) => { + obj[headers[i]] = val; + }); + return obj; + }); +} + +/** + * Make table from generated or mutated (from parseTable) table data + * @param headers List of strings to use as table headers, must be keys in object + * @param data Table row data + * @param decorator (Optional) decorator function to change table row elements + */ +export function makeTable( + headers: string[], + data: TableData, + decorator?: (data: TableRowData, tr: HTMLTableRowElement) => void +): HTMLTableElement { + const table = document.createElement("table"); + if (data.length < 1) { + return table; + } + // Make header row + const headerRow = document.createElement("tr"); + headers.forEach((head) => { + const headerCell = document.createElement("th"); + headerCell.appendChild(document.createTextNode(head)); + headerRow.appendChild(headerCell); + }); + table.appendChild(headerRow); + + // Make rows + data.forEach((row) => { + const tableRow = document.createElement("tr"); + headers.forEach((key) => { + let cell = null; + if (row[key].tagName === "TD" || row[key].tagName === "TH") { + cell = row[key]; + } else { + cell = document.createElement("td"); + cell.appendChild(row[key]); + } + tableRow.appendChild(cell); + }); + if (decorator) { + decorator(row, tableRow); + } + table.appendChild(tableRow); + }); + + return table; +} + +export default { findParent, parseTable, makeTable }; diff --git a/style/main.scss b/style/main.scss index 46d46cf..531a7a6 100644 --- a/style/main.scss +++ b/style/main.scss @@ -4,3 +4,4 @@ $nanotrasen: #384e68; @import "search.scss"; @import "pages/global.scss"; @import "pages/chemistry.scss"; +@import "pages/virology.scss"; diff --git a/style/pages/chemistry.scss b/style/pages/chemistry.scss index 3a64ce4..dccffa8 100644 --- a/style/pages/chemistry.scss +++ b/style/pages/chemistry.scss @@ -1,127 +1,136 @@ -.bgus_twistie:after { - color: red; - display: inline-block; - font-weight: bold; - margin-left: 0.2em; - content: "⯆"; -} -.bgus_collapsed > .bgus_twistie:after { - content: "⯈"; -} -div.tooltiptext { - display: none; - border: 1px solid #384e68; - background: linear-gradient(to bottom, darken(#384e68, 20%), darken(#384e68, 25%)); -} -span.bgus_nested_element:not(.bgus_collapsed) + div.tooltiptext { - z-index: unset; - visibility: inherit; - display: block; - opacity: 1; - position: relative; - width: auto; - border-left-width: 3px; - margin-left: 5px; - margin-top: 5px; - font-size: 8pt; - padding: 5px 8px; - line-height: 10pt; +div[data-tab="Guide_to_chemistry"] { + .bgus_twistie:after { + color: red; + display: inline-block; + font-weight: bold; + margin-left: 0.2em; + content: "⯆"; + } + + .bgus_collapsed > .bgus_twistie:after { + content: "⯈"; + } div.tooltiptext { - margin-left: -5px; + display: none; + border: 1px solid #384e68; + background: linear-gradient(to bottom, darken(#384e68, 20%), darken(#384e68, 25%)); } -} -div[data-tab="Guide_to_chemistry"] { - table.wikitable > tbody > tr > td:nth-child(2) { - width: 45%; - padding: 10px; + + span.bgus_nested_element:not(.bgus_collapsed) + div.tooltiptext { + z-index: unset; + visibility: inherit; + display: block; + opacity: 1; + position: relative; + width: auto; + border-left-width: 3px; + margin-left: 5px; + margin-top: 5px; + font-size: 8pt; + padding: 5px 8px; + line-height: 10pt; + + div.tooltiptext { + margin-left: -5px; + } } + table.wikitable { border: 0 !important; + .table-head { text-align: center; } + th { background-color: darken($nanotrasen, 5%) !important; } - } - .bgus_fz_selected { - background: $nanotrasen !important; - th, - td { - border-top: 2px solid lighten($nanotrasen, 20%); - border-bottom: 2px solid lighten($nanotrasen, 15%); - } - th { - background: lighten($nanotrasen, 5%) !important; - } - div.tooltiptext { - border-color: lighten($nanotrasen, 20%); - background: darken($nanotrasen, 10%); - } - } -} -body.bgus_cbox { - input[type="checkbox"] + span[data-src]:before { - display: inline-block; - width: 1.5em; - content: "[_]"; - } - input[type="checkbox"]:checked + span[data-src]:before { - content: "[X]"; - } - input[type="checkbox"]:checked + span[data-src] { - text-decoration: line-through; - } - input[type="checkbox"] + span[data-src] { - cursor: pointer; - } - input[type="checkbox"] + span[data-src]:before, - input[type="checkbox"] + span[data-src] { - color: orange; - font-weight: bold; - } - input[type="checkbox"]:checked + span[data-src]:before, - input[type="checkbox"]:checked + span[data-src] { - color: green; - } -} -.reagent-ext { - .reagent-header { - font-size: 12pt; - text-align: left; - padding: 10pt; - padding-bottom: 0; - span:last-child { - margin-left: 0.5em; + & > tbody > tr > td:nth-child(2) { + width: 45%; + padding: 10px; + } + + .bgus_fz_selected { + background: $nanotrasen !important; + th, + td { + border-top: 2px solid lighten($nanotrasen, 20%); + border-bottom: 2px solid lighten($nanotrasen, 15%); + } + th { + background: lighten($nanotrasen, 5%) !important; + } + div.tooltiptext { + border-color: lighten($nanotrasen, 20%); + background: darken($nanotrasen, 10%); + } } } - p { - font-size: 8pt; - font-weight: 300; - line-height: 1.4em; - word-spacing: -0.1em; + + body.bgus_cbox { + input[type="checkbox"] + span[data-src]:before { + display: inline-block; + width: 1.5em; + content: "[_]"; + } + input[type="checkbox"]:checked + span[data-src]:before { + content: "[X]"; + } + input[type="checkbox"]:checked + span[data-src] { + text-decoration: line-through; + } + input[type="checkbox"] + span[data-src] { + cursor: pointer; + } + input[type="checkbox"] + span[data-src]:before, + input[type="checkbox"] + span[data-src] { + color: orange; + font-weight: bold; + } + input[type="checkbox"]:checked + span[data-src]:before, + input[type="checkbox"]:checked + span[data-src] { + color: green; + } } - .treatment { - font-size: 10pt; - } - .metabolism:before { - font-size: 9pt; - content: "Metabolism rate: "; - font-weight: bold; - } - .overdose, - .addiction { - font-size: 9pt; - font-weight: bold; - } - .overdose:before { - color: #ffae68; - content: "Overdose at "; - } - .addiction:before { - color: #ffdf97; - content: "Addiction at "; + + .reagent-ext { + .reagent-header { + font-size: 12pt; + text-align: left; + padding: 10pt; + padding-bottom: 0; + span:last-child { + margin-left: 0.5em; + } + } + p { + font-size: 8pt; + font-weight: 300; + line-height: 1.4em; + word-spacing: -0.1em; + } + .treatment { + font-size: 10pt; + } + .metabolism:before { + font-size: 9pt; + content: "Metabolism rate: "; + font-weight: bold; + } + .overdose, + .addiction { + font-size: 9pt; + font-weight: bold; + } + .overdose:before { + color: #ffae68; + content: "Overdose at "; + } + .addiction:before { + color: #ffdf97; + content: "Addiction at "; + } } } diff --git a/style/pages/virology.scss b/style/pages/virology.scss new file mode 100644 index 0000000..5285470 --- /dev/null +++ b/style/pages/virology.scss @@ -0,0 +1,71 @@ +div[data-tab="Infections"] { + .disease-ext { + width: 100%; + th, + td:first-child { + background-color: #2f4257; + } + td:nth-child(2) { + width: 30vw; + max-width: 300px; + text-align: center; + } + .disease-name { + font-size: 12pt; + text-align: left; + padding: 10pt; + padding-bottom: 0; + margin-bottom: 10pt; + } + p { + font-size: 8pt; + font-weight: 300; + line-height: 1.2em; + word-spacing: -0.1em; + } + .vector { + font-size: 9pt; + &:before { + content: "Vector: "; + font-weight: bold; + } + } + .source { + font-size: 9pt; + &:before { + content: "Source: "; + font-weight: bold; + } + } + .spread { + font-size: 9pt; + &:before { + content: "Spread: "; + font-weight: bold; + } + } + p { + margin: 5pt 0; + } + .description { + margin: 10pt 0; + line-height: 1.5em; + } + + .bgus_fz_selected { + background: $nanotrasen !important; + th, + td { + border-top: 2px solid lighten($nanotrasen, 20%); + border-bottom: 2px solid lighten($nanotrasen, 15%); + } + th { + background: lighten($nanotrasen, 5%) !important; + } + div.tooltiptext { + border-color: lighten($nanotrasen, 20%); + background: darken($nanotrasen, 10%); + } + } + } +}