@@ -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", | |||
{ | |||
@@ -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; | |||
@@ -184,14 +184,14 @@ export function chemistryScript(root: HTMLElement): void { | |||
// Init fuzzy search with elements | |||
const el = Array.from( | |||
root.querySelectorAll<HTMLElement>( | |||
"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, | |||
@@ -1,8 +1,53 @@ | |||
import { parseTable, makeTable } from "../utils"; | |||
import { registerSearchEntries } from "../search"; | |||
export function processVirology(root: HTMLElement): void { | |||
const diseaseTable = root.querySelector<HTMLElement>( | |||
"#Simple_Diseases .wikitable" | |||
); | |||
const diseases = parseTable(diseaseTable).map((row) => { | |||
const diseaseBlock = document.createElement("td"); | |||
diseaseBlock.innerHTML = ` | |||
<div class="disease-name">${row["Disease Name"].innerHTML}</div> | |||
<p class="vector">${row["Vector Name"].innerHTML}</p> | |||
<p class="source">${row["Source"].innerHTML}</p> | |||
<p class="spread">${row["Spread"].innerHTML}</p> | |||
<p class="description">${row["Description"].innerHTML}</p> | |||
`; | |||
return { | |||
Disease: diseaseBlock, | |||
Cure: row["Cure"], | |||
}; | |||
}); | |||
const diseaseBetterTable = makeTable(["Disease", "Cure"], diseases); | |||
diseaseBetterTable.className = "disease-ext wikitable"; | |||
diseaseTable.replaceWith(diseaseBetterTable); | |||
const symptomsTable = root.querySelector<HTMLElement>( | |||
"#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<HTMLElement>(".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, | |||
}; |
@@ -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) => { | |||
@@ -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<string, HTMLElement>; | |||
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<HTMLTableRowElement>("th") | |||
).map((th) => th.textContent.trim()); | |||
return valueRows.map((tr) => { | |||
const obj = {}; | |||
tr.querySelectorAll<HTMLElement>("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 }; |
@@ -4,3 +4,4 @@ $nanotrasen: #384e68; | |||
@import "search.scss"; | |||
@import "pages/global.scss"; | |||
@import "pages/chemistry.scss"; | |||
@import "pages/virology.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; | |||
} | |||
& > 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%); | |||
} | |||
} | |||
} | |||
.bgus_fz_selected { | |||
background: $nanotrasen !important; | |||
th, | |||
td { | |||
border-top: 2px solid lighten($nanotrasen, 20%); | |||
border-bottom: 2px solid lighten($nanotrasen, 15%); | |||
body.bgus_cbox { | |||
input[type="checkbox"] + span[data-src]:before { | |||
display: inline-block; | |||
width: 1.5em; | |||
content: "[_]"; | |||
} | |||
th { | |||
background: lighten($nanotrasen, 5%) !important; | |||
input[type="checkbox"]:checked + span[data-src]:before { | |||
content: "[X]"; | |||
} | |||
div.tooltiptext { | |||
border-color: lighten($nanotrasen, 20%); | |||
background: darken($nanotrasen, 10%); | |||
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; | |||
} | |||
} | |||
} | |||
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; | |||
.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 "; | |||
} | |||
} | |||
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 "; | |||
} | |||
} |
@@ -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%); | |||
} | |||
} | |||
} | |||
} |