import {$, doAfterLoad, footer, header, nav, showPage} from "@fwdekker/template"; const storageKey = "/tools/random-fo76//selected-signatures"; const signatureColCount = 8; /** * Fetches the API response given a query. * * @param query the query to send to the API * @param callback the function to execute with the array of signatures * @param handle the function to execute if signatures could not be downloaded */ const fetchFromApi = (query, callback, handle) => { fetch(`api.php?${query}`) .then(response => { if (!response.ok) { if (handle) handle(response); console.error(response); throw new Error(`Failed to execute query '${query}' on API.`); } return response.json(); }) .then(response => callback(response)); } /** * Returns an array of the signatures that are currently selected. */ const getSelectedSignatures = () => { const signatures = []; const selectedCheckboxes = document.querySelectorAll("#signatures input:checked"); for (let i = 0; i < selectedCheckboxes.length; i++) { const selectedCheckbox = selectedCheckboxes[i]; signatures.push(selectedCheckbox.value); } return signatures; }; /** * Selects the indicated signatures, and deselects all others. * * @param signatures the array of signatures to select */ const setSelectedSignatures = signatures => { const checkboxes = document.querySelectorAll("#signatures input"); for (let i = 0; i < checkboxes.length; i++) checkboxes[i].checked = false; for (let i = 0; i < signatures.length; i++) $(`#signature-${signatures[i]}`).checked = true; updateSignatureToggle(); }; /** * Selects all signatures. */ const setAllSignatures = checked => { const checkboxes = document.querySelectorAll("#signatures input"); for (let i = 0; i < checkboxes.length; i++) checkboxes[i].checked = checked; saveSelectedSignaturesToStorage(); updateSignatureToggle(); }; /** * (De)selects signatures based on the selection stored in local storage. */ const loadSelectedSignaturesFromStorage = () => { const item = localStorage.getItem(storageKey); let signatures; if (item === null) signatures = []; else signatures = item.split(","); setSelectedSignatures(signatures); }; /** * Saves the currently-selected signatures to local storage. */ const saveSelectedSignaturesToStorage = () => localStorage.setItem(storageKey, getSelectedSignatures().join(",")); /** * Updates the button used to toggle all signatures on or off. */ const updateSignatureToggle = () => { const signatureToggle = $("#signatureToggle"); if (getSelectedSignatures().length === document.querySelectorAll("#signatures input").length) { signatureToggle.innerHTML = "Deselect all signatures"; signatureToggle.onclick = () => setAllSignatures(false); } else { signatureToggle.innerHTML = "Select all signatures"; signatureToggle.onclick = () => setAllSignatures(true); } }; /** * Creates buttons for the signatures and adds them to the form. * * @param signatures an array of signatures to create buttons for */ const createSignatureButtons = signatures => { const form = $("#signatures"); form.innerHTML = ""; let row; for (let i = 0; i < signatures.length; i++) { const signature = signatures[i]; if (i % signatureColCount === 0) { if (row !== undefined) form.appendChild(row); row = document.createElement("div"); row.className = "row"; } const col = document.createElement("div"); col.className = "column"; const label = document.createElement("label"); label.htmlFor = `signature-${signature}`; label.innerHTML = signature; col.appendChild(label); const checkbox = document.createElement("input"); checkbox.type = "checkbox"; checkbox.id = `signature-${signature}`; checkbox.name = `signature-${signature}`; checkbox.value = signature; checkbox.onclick = () => { updateSignatureToggle(); saveSelectedSignaturesToStorage(); }; col.appendChild(checkbox); row.appendChild(col); } if (row !== undefined) form.appendChild(row); }; /** * Displays a record on the page. * * @param record the record to display */ const showRecord = (record) => { $("#output").innerHTML = JSON.stringify(record, null, 4); const scrollingElement = (document.scrollingElement || document.body); scrollingElement.scrollTop = scrollingElement.scrollHeight; }; // Apply template doAfterLoad(() => { $("#nav").appendChild(nav("/Tools/Random FO76/")); $("#header").appendChild(header({ title: "Random Fallout 76 record", description: "Retrieve a random record from the Fallout 76 game files" })); $("#footer").appendChild(footer({ author: "Felix W. Dekker", authorURL: "https://fwdekker.com/", license: "MIT License", licenseURL: "https://git.fwdekker.com/FWDekker/random-fo76/src/branch/master/LICENSE", vcs: "git", vcsURL: "https://git.fwdekker.com/FWDekker/random-fo76/", version: "v%%VERSION_NUMBER%%" })); showPage(); }); // Load page from API doAfterLoad(() => { fetchFromApi("action=get-meta", meta => { $("#gameVersion").innerHTML = meta["game_version"]; $("#dumpsVersion").innerHTML = meta["dumps_version"]; }, () => { $("#gameVersion").innerHTML = "Error"; $("#dumpsVersion").innerHTML = "Error"; } ); fetchFromApi("action=list-signatures", signatures => { createSignatureButtons(signatures); loadSelectedSignaturesFromStorage(); }, () => { const form = $("#signatureForm"); form.style.color = "red"; form.innerHTML = "Error: Failed to download signatures. Try reloading the page."; } ); }); // Install handlers doAfterLoad(() => { $("#submit").onclick = () => { $("#output").innerHTML = "Fetching record... please wait"; const selectedSignatures = getSelectedSignatures(); fetchFromApi(`action=get-random&signatures=${selectedSignatures.join(",")}`, record => showRecord(record) ); }; });