`;
/* ############################## create all main entries ############################## */
for (let section in sections) {
entries = sections[section].entries;
/* starts a new
\n\n`;
}
/* console.groupCollapsed("finalHTMLFill");
console.log(finalHTMLFill);
console.groupEnd(); */
/* Final single HTML access and fill here */
document.getElementById("generated").innerHTML = finalHTMLFill;
// finish benchmarking
benchmarkTimes.GenerateInnerHTML.timeEnd = new Date();
}
function SectionStart(section) {
return `
\n`;
}
/**
* Replaces the h2 titles with max percent values as read from the database
*/
function CompletionFillNoSave(section) {
let id = "";
let h2 = "";
let h2id = "";
let mp = ""; // max Percent
// let cl = ""; // class
id = section.id;
h2 = section.h2;
h2id = "h2-" + section.id;
mp = `
${(id === "hk-intro") ? 0: section.maxPercent}%
`;
if (!section.hasOwnProperty("maxPercent")) mp = "";
/* return [
`
`,
`
${h2}${mp}
`,
"\n"
].join(""); */
return `
${h2}${mp}
`;
}
/**
* Replaces the h2 titles with a current percent/max percent values as read from the database
*/
function CompletionFill(section) {
let h2 = section.h2;
let h2id = `
`;
let cl = "";
let clGreen = "box-green";
let clRed = "box-red";
let cp = 0; // current Percent
let mp = 0; // max Percent
let fillText = "";
(section.hasOwnProperty("percent")) ? cp = section.percent: cp = 0;
// Don't use percent-box for Essentials, Achievements, Statistics
if (!section.hasOwnProperty("maxPercent")) {
fillText = "";
}
// otherwise use percent-box with values cp/mp%
else {
mp = section.maxPercent;
if (section.id === "hk-maskshards") {
let perc = section.percent;
(perc % 4) ? cp = Math.floor(perc / 4): cp = perc / 4;
} else if (section.id === "hk-vesselfragments") {
let perc = section.percent;
(perc % 3) ? cp = Math.floor(perc / 3): cp = perc / 3;
}
// switches the box to red when a section (h2) is 0
if (cp === 0) {
cl = ` ${clRed}`;
}
// switches the box to green when a section (h2) is completed
else if (cp === mp) {
cl = ` ${clGreen}`;
}
// default is blue (partially completed and starting value)
else cl = "";
// needed for Game Status to show percentage properly (adds a slash for all boxes except the Game Status one)
if (section.id != "hk-intro") cp += "/";
fillText = `
${(section.id === "hk-intro") ? cp: cp + section.maxPercent}%
`;
}
return `\t${h2id}${h2}${fillText}\n`;
}
/* function SingleEntryFill(section, entry) { */
function SingleEntryFill(obj) {
/*
let icon = "";
let iconGreen = SYMBOL_TRUE;
let iconRed = SYMBOL_FALSE;
let iconClock = SYMBOL_CLOCK;
let iconNull = SYMBOL_EMPTY;
let textPrefix = "";
let textSuffix = "";
let textFill = "";
let Img = "";
let maskNormal = `

`;
let maskSteel = `

`;
let soulNormal = `

`;
let notchNormalImage = `

`;
let notchFilledImage = `

`;
let notchOvercharmedImage = `

`;
let geoNormalImage = `

`;
let geoShadeImage = `

`;
let wiki = "";
let div = `
`;
let divFlex = `
`;
let b = ["
", ""];
let p = "
";
let span = ["", ""];
let spoiler = ["", ""];
let spoilerAfter = "";
if (entry.hasOwnProperty("icon")) {
switch (entry.icon) {
case "clock":
icon = iconClock;
break;
case "green":
icon = iconGreen;
break;
case "red":
icon = iconRed;
break;
default:
icon = iconNull;
}
} else {
icon = iconRed;
}
if (entry.hasOwnProperty("name")) {
textPrefix = entry.name;
}
if (entry.hasOwnProperty("spoiler")) {
textSuffix = entry.spoiler;
}
if (entry.hasOwnProperty("wiki")) {
wiki = entry.wiki;
}
if (!textPrefix.length) b = ["", ""];
if (wiki.length) b = [`
`, ""];
// #################### Different behaviour depending on the section #######################
switch (section) {
case "intro":
b = ["", ""];
span = ["
", ""];
// Different text and images for each entry in the "Game Status" section
switch (entry.id) {
case "gameCompletion":
textSuffix = `${entry.spoiler} %`;
break;
case "health":
div = divFlex;
span = ["", ""];
(entry.permadeathMode) ? Img = maskSteel: Img = maskNormal;
for (let i = 0, total = entry.amountTotal; i < total; i++) {
textSuffix += Img;
}
textSuffix += `${p}
(${entry.amountTotal})`;
p = "";
break;
case "soul":
div = divFlex;
span = ["", ""];
Img = soulNormal;
for (let i = 0, total = Math.round(entry.amountTotal / 33); i < total; i++) {
textSuffix += Img;
}
textSuffix += `${p}
(${Math.round(entry.amountTotal / 33)})`;
p = "";
break;
case "notches":
div = divFlex;
span = ["", ""];
// First, check filled (used) notches and fill them (skips if no filled notches)
if (entry.amountFilled > 0) {
for (let i = 0, total = entry.amountFilled; i < total; i++) {
textSuffix += notchFilledImage;
}
}
// Second, check overcharmed notches and fill them (skips if player is not overcharmed)
if (entry.amountOvercharmed > 0) {
for (let i = 0, total = entry.amountOvercharmed; i < total; i++) {
textSuffix += notchOvercharmedImage;
}
}
// Last, fill all unused notches
if (entry.amountUnused > 0) {
for (let i = 0, total = entry.amountUnused; i < total; i++) {
textSuffix += notchNormalImage;
}
}
textSuffix += `${p}
(${entry.amountTotal})`;
break;
case "geo":
div = divFlex;
span = ["", ""];
textSuffix += `${geoNormalImage}
${entry.amount}`;
// Show Shade Geo value and image only if Shade has at least 1 Geo on it
if (entry.amountShade > 0) textSuffix += `${p}+${geoShadeImage}
${entry.amountShade}`;
// Show also total Geo (Geo + Shade Geo) if player has at least 1 geo alongside the shade geo
if (entry.amount > 0 && entry.amountShade > 0) textSuffix += `${p}=${p}
${entry.amountTotal}`;
p = "";
break;
default:
}
// Optimized only for the "intro" section!
if (entry.hasOwnProperty("spoilerAfter")) {
spoilerAfter = ` ${entry.spoilerAfter}`;
span[1] = "";
}
break;
case "hints":
b = ["", ""];
span = ["
", ""];
icon = iconNull;
break;
default:
span = ["
", ""];
spoiler = ["
", ""];
if (entry.hasOwnProperty("amount")) {
if (entry.hasOwnProperty("disabled")) {
if (entry.disabled !== true) {
textPrefix += `: ${entry.amount}`;
}
} else {
textPrefix += `: ${entry.amount}`;
}
}
if (entry.hasOwnProperty("amountTotal")) {
textPrefix += ` / ${entry.amountTotal}`;
}
if (entry.hasOwnProperty("id")) {
switch (entry.id) {
case "geoRocks":
case "itemsDiscovered":
textPrefix += `: ${entry.notActivated} | ${entry.activated} | ${entry.discoveredTotal}`;
break;
case "zoteStatus":
case "nailsmithStatus":
if (entry.hasOwnProperty("currentName") && entry.hasOwnProperty("currentSpoiler")) {
textPrefix = entry[entry.currentName];
textSuffix = entry[entry.currentSpoiler];
}
break;
default:
}
}
if (entry.hasOwnProperty("disabled")) {
if (entry.disabled === true) {
textPrefix = `
${textPrefix}`;
}
}
if (textSuffix.length && textPrefix.length) textSuffix = `— ${textSuffix}`;
if (textPrefix.includes("
")) textSuffix = `${textSuffix}`;
}
*/
/* return [
div,
icon,
`${b[0]}${textPrefix}${b[1]}`,
span[0],
p,
spoiler[0],
`${textSuffix}${spoilerAfter}`,
spoiler[1],
span[1],
"\n"
].join("");
*/
return [
obj.div,
obj.icon,
`${obj.b[0]}${obj.textPrefix}${obj.b[1]}`,
obj.span[0],
obj.p,
obj.spoiler[0],
`${obj.textSuffix}${obj.spoilerAfter}`,
obj.spoiler[1],
obj.span[1],
"
\n"
].join("");
}
/**
* Adds HTML string to an element with a given ID.
* @param {object} divId object containing div ID of the HTML element to append to
* @param {string} content HTML contents to append
*/
function AppendHTML(divId, content) {
document.getElementById(divId.id).innerHTML += "\n" + content;
}
/**
* Toggles display of "hk-hints". On click with no parameters or on demand when called with a parameter
* @param {string} param "hide", "show" or none (optional)
*/
function CheckboxHintsToggle(param = "none") {
let checkboxId = document.getElementById("checkbox-hints");
switch (param) {
case "hide":
document.getElementById("hk-hints").classList.add("hidden");
checkboxId.value = "hints-off";
checkboxId.checked = false;
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxHints", "unchecked");
}
break;
case "show":
document.getElementById("hk-hints").classList.remove("hidden");
checkboxId.value = "hints-on";
checkboxId.checked = true;
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxHints", "checked");
}
break;
default:
// This runs when the checkbox is not checked
if (checkboxId.checked === false) {
document.getElementById("hk-hints").classList.add("hidden");
checkboxId.value = "hints-off";
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxHints", "unchecked");
}
}
// This runs when the checkbox is checked
else {
document.getElementById("hk-hints").classList.remove("hidden");
checkboxId.value = "hints-on";
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxHints", "checked");
}
}
}
}
/**
* Toggles display of ".spoiler-span" class. On click with no parameters or on demand when called with a parameter
* @param {string} param "hide", "show" or none (optional)
*/
function CheckboxSpoilersToggle(param = "none") {
let checkboxId = document.getElementById("checkbox-spoilers");
let allClassElements = document.querySelectorAll(".spoiler-span");
let allClassElementsRed = document.querySelectorAll(".spoiler-red");
let length = allClassElements.length;
let lengthRed = allClassElementsRed.length;
switch (param) {
case "hide":
for (let i = 0; i < length; i++) {
allClassElements[i].classList.add("hidden");
}
for (let i = 0; i < lengthRed; i++) {
allClassElementsRed[i].classList.add("blurred");
}
checkboxId.value = "spoilers-off";
checkboxId.checked = false;
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxSpoilers", "unchecked");
}
break;
case "show":
for (let i = 0; i < length; i++) {
allClassElements[i].classList.remove("hidden");
}
for (let i = 0; i < lengthRed; i++) {
allClassElementsRed[i].classList.remove("blurred");
}
checkboxId.value = "spoilers-on";
checkboxId.checked = true;
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxSpoilers", "checked");
}
break;
default:
// This runs when the checkbox is not checked
if (checkboxId.checked === false) {
for (let i = 0; i < length; i++) {
allClassElements[i].classList.add("hidden");
}
for (let i = 0; i < lengthRed; i++) {
allClassElementsRed[i].classList.add("blurred");
}
checkboxId.value = "spoilers-off";
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxSpoilers", "unchecked");
}
break;
}
// This runs when the checkbox is checked
else {
for (let i = 0; i < length; i++) {
allClassElements[i].classList.remove("hidden");
}
for (let i = 0; i < lengthRed; i++) {
allClassElementsRed[i].classList.remove("blurred");
}
checkboxId.value = "spoilers-on";
// remember this choice for subsequent page visits and browser restarts
if (StorageAvailable('localStorage')) {
localStorage.setItem("hkCheckboxSpoilers", "checked");
}
}
}
}
/**
* Detects whether Storage is both supported and available.
* MDN WebDocs https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#feature-detecting_localstorage
* @param {Storage} type type of storage. Ex. "localStorage" or "sessionStorage"
* @returns {Boolean}
*/
function StorageAvailable(type) {
var storage;
try {
storage = window[type];
var x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (e) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(storage && storage.length !== 0);
}
}
/* ----------------------- Event Listeners -------------------------- */
document.addEventListener("scroll", () => {
TogglePageScrollElement(
/* the document element root () */
ROOT,
/* Which element to toggle visibility */
SCROLL_BUTTON,
/* How far the user has to scroll to show the element */
0.1);
});
SCROLL_BUTTON.addEventListener("click", () => {
ScrollToElement(ROOT);
});
// Checkboxes functions
document.getElementById("checkbox-hints").addEventListener("click", CheckboxHintsToggle, false);
document.getElementById("checkbox-spoilers").addEventListener("click", CheckboxSpoilersToggle, false);
/* ------------------------- Exports ------------------------------- */
export {
GenerateInnerHTML,
AppendHTML,
CheckboxHintsToggle,
CheckboxSpoilersToggle,
StorageAvailable
};