document.addEventListener("DOMContentLoaded", init); function init() { loadDomain(); document.querySelector("#toggle").addEventListener("click", toggle); restore(); document.querySelector("#preset").addEventListener("change", showOther); document.querySelector("#options").addEventListener("submit", save); document.querySelector("#restore").addEventListener("click", restore); } /*TODO except browser like about*/ /* Loads and displays information about the current domain */ function loadDomain() { let tabs = browser.tabs.query({ active: true, currentWindow: true }); tabs.then((tabs) => { const hostname = new URL(tabs[0].url).hostname; document.querySelector("#domain").innerHTML = hostname; let storage = browser.storage.local.get("domains"); storage.then((storage) => { const hostname = document.querySelector("#domain").innerHTML; const domains = storage.domains; if (domains === undefined) { browser.storage.local.set({"domains": []}); } else if (domains.includes(hostname)) { toggleButton(); } }, logError); }, logError); } /* Adds or removes the current domain from storage */ function toggle() { let storage = browser.storage.local.get("domains"); storage.then((storage) => { const hostname = document.querySelector("#domain").innerHTML; let domains = storage.domains; const index = domains.indexOf(hostname); if (index > -1) { domains.splice(index, 1); } else { domains.push(hostname); } browser.storage.local.set({"domains": domains}); }, logError); toggleButton(); browser.tabs.reload(); } /* Toggles the displayed button state */ function toggleButton() { document.querySelector("#toggle").classList.toggle("is-on"); let state = document.querySelector("#state"); let button = document.querySelector("#toggle"); state.classList.toggle("is-on"); if (state.innerHTML == "disabled") { state.innerHTML = "enabled" button.title = "Toggle to disable"; } else { state.innerHTML = "disabled"; button.title = "Toggle to enable"; } } /* Gets saved options and loads them */ function restore() { let options = browser.storage.local.get(); options.then(load, logError); } /* Fills form fields with stored options */ function load(options) { if (options.name === undefined) { options.name = ""; options.preset = ""; options.other = {}; options.pov = ""; options.also = {}; } document.querySelector("#name").value = options.name; document.querySelector("#preset").value = options.preset; loadOther(options); document.querySelector("#pov").value = options.pov; loadAlso(options); } /* Helper for load, sets contents of other in HTML */ function loadOther(options) { if (Object.keys(options.other).length === 0) { return; } document.querySelector("#other").querySelectorAll("input, select").forEach((pronoun) => { pronoun.value = options.other[pronoun.id]; }); showOther(); } /* Helper for load, sets contents of also in HTML */ function loadAlso(options) { const also = document.querySelector("#also"); also.innerHTML = ""; if (Object.keys(options.also).length === 0) { addFinal(also, 0); return; } let li; let i = 0; Object.entries(options.also).forEach(([key, value]) => { li = createLi(i); li.querySelector("#lhs-" + i).value = key; li.querySelector("#rhs-" + i).value = value; also.append(li); i++; }); addFinal(also, i); } /* Saves options */ function save() { browser.storage.local.set({ "name": document.querySelector("#name").value, "preset": document.querySelector("#preset").value, "other": saveOther(), "pov": document.querySelector("#pov").value, "also": saveAlso() }); browser.tabs.reload(); } /* Helper for save, gets contents of other */ function saveOther() { const other = {}; document.querySelector("#other").querySelectorAll("input, select").forEach((pronoun) => { other[pronoun.id] = pronoun.value; }); return other; } /* Helper for save, gets contents of also */ function saveAlso() { const also = {}; const lhs = document.querySelectorAll(".lhs"); const rhs = document.querySelectorAll(".rhs"); for (let i = 0; i < lhs.length; i++) { if (lhs[i].value == "") { continue; } also[lhs[i].value] = rhs[i].value; } return also; } /* Creates the HTML for a new also replacement */ function createLi(index) { const li = document.createElement("li"); li.classList.add("unhide"); const lhs = document.createElement("input"); lhs.type = "text"; lhs.className = "lhs"; lhs.id = "lhs-" + index; lhs.name = lhs.id; const rhs = document.createElement("input"); rhs.type = "text"; rhs.className = "rhs"; rhs.id = "rhs-" + index; rhs.name = rhs.id; const rhsLabel = document.createElement("label"); rhsLabel.for = rhs.id; rhsLabel.innerHTML = "with"; const button = document.createElement("button"); button.type = "button"; button.id = "delete-" + index; button.className = "delete" button.innerHTML = ""; button.addEventListener("click", removeLi); li.append(lhs); li.append(rhsLabel); li.append(rhs); li.append(button); return li; } /* Adds a new also replacement when the last lhs is filled */ function addLi() { if (this.value == "") { return; } const index = document.querySelectorAll(".lhs").length; const li = createLi(index); setFinal(this.parentNode, false); setFinal(li, true); document.querySelector("#also").append(li); li.classList.add("hide"); requestAnimationFrame(() => { li.classList.remove("hide") }) } /* Removes an item from the list of also replacements */ async function removeLi() { this.parentNode.classList.add("hide"); let fields = this.parentNode.querySelectorAll("input, button"); fields.forEach((field) => { field.disabled = true; }); await sleep(200); /* TODO make 300 different if reduced motion */ let also = document.querySelector("#also"); also.removeChild(this.parentNode); let list = also.querySelectorAll("li"); list.forEach((li, index) => { lhs = li.querySelector(".lhs"); lhs.id = "lhs-" + index; lhs.name = lhs.id; rhs = li.querySelector(".rhs"); rhs.id = "rhs-" + index; rhs.name = rhs.id; rhsLabel = li.querySelector("label"); rhsLabel.for = rhs.id; }); } /* Adds a final, empty field to the list of also replacements */ function addFinal(also, index) { const li = createLi(index); setFinal(li, true); also.append(li); return; } /* Shows the button to clear the field if isFinal is true */ function setFinal(li, isFinal) { if (isFinal) { li.querySelector(".lhs").addEventListener("change", addLi); li.classList.add("hide-button"); } else { li.querySelector(".lhs").removeEventListener("change", addLi); li.classList.remove("hide-button"); } } /* Displays more options for pronouns if "other" is selected */ function showOther() { let other = document.querySelector("#other"); let fields = other.querySelectorAll("input, select"); if (document.querySelector("#preset").value == "other") { other.classList.remove("hide"); fields.forEach((field) => { field.disabled = false; }); } else { other.classList.add("hide"); fields.forEach((field) => { field.disabled = true; }); } } /* Sleep */ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /* Required by then */ function logError(error) { console.log(`Error: ${error}`); }