metamorpov/src/popup.js

286 lines
7.8 KiB
JavaScript

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);
}
/* 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("reveal-moderate");
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 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2z\"/><path d=\"m12 9 6 6\"/><path d=\"m18 9-6 6\"/></svg>";
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("shrink");
requestAnimationFrame(() => {
li.classList.remove("shrink")
})
}
/* Removes an item from the list of also replacements */
async function removeLi() {
let li = this.parentNode;
li.classList.add("shrink");
let fields = li.querySelectorAll("input, button");
fields.forEach((field) => {
field.disabled = true;
});
await sleep(300); /* Matches var(--speed-slow) */
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.querySelector("button").classList.add("hide");
} else {
li.querySelector(".lhs").removeEventListener("change", addLi);
li.querySelector("button").classList.remove("hide");
}
}
/* 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("flat");
fields.forEach((field) => {
field.disabled = false;
});
} else {
other.classList.add("flat");
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}`);
}