aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuchen Pei <hi@ypei.me>2022-07-28 14:45:32 +1000
committerYuchen Pei <hi@ypei.me>2022-07-28 14:45:32 +1000
commitb98cb70b1bcd5b211aaa5d2675f96416911c0647 (patch)
tree88c633bc089d45c79a30bc9df8d69b5a8a206430
parentb8f2995c86da0edeac9178187124696eb412a8e1 (diff)
clean up code in prefs panel
-rw-r--r--html/preferences_panel/pref.js120
-rw-r--r--test/spec/LibreJSSpec.js2
2 files changed, 63 insertions, 59 deletions
diff --git a/html/preferences_panel/pref.js b/html/preferences_panel/pref.js
index c3597e1..a1c6cb5 100644
--- a/html/preferences_panel/pref.js
+++ b/html/preferences_panel/pref.js
@@ -25,29 +25,32 @@
const LIST_NAMES = ["white", "black"];
- var Model = {
+ const Model = {
lists: {},
prefs: null,
malformedUrl(url) {
- let error = null;
try {
- let objUrl = new URL(url);
- url = objUrl.href;
+ const objUrl = new URL(url);
+ const newUrl = objUrl.href;
if (!objUrl.protocol.startsWith("http")) {
- error = "Please enter http:// or https:// URLs only";
- } else if (!/^[^*]+\*?$/.test(url)) {
- error = "Only one single trailing path wildcard (/*) allowed";
+ return "Please enter http:// or https:// URLs only";
+ } else if (!/^[^*]+\*?$/.test(newUrl)) {
+ return "Only one single trailing path wildcard (/*) allowed";
}
} catch (e) {
if (/^https?:\/\/\*\./.test(url)) {
return this.malformedUrl(url.replace("*.", ""));
}
- error = "Invalid URL";
- if (url && !url.includes("://")) error += ": missing protocol, either http:// or https://";
- else if (url.endsWith("://")) error += ": missing domain name";
+ const prefix = "Invalid URL";
+ if (url && !url.includes("://"))
+ return prefix + ": missing protocol, either http:// or https://";
+ else if (url.endsWith("://"))
+ return prefix + ": missing domain name";
+ else
+ return prefix;
}
- return error;
+ return null;
},
async save(prefs = this.prefs) {
@@ -63,7 +66,7 @@
},
async addToList(list, ...items) {
- let other = list === Model.lists.black ? Model.lists.white : Model.lists.black;
+ const other = list === Model.lists.black ? Model.lists.white : Model.lists.black;
this.saving = true;
try {
await Promise.all([
@@ -75,8 +78,9 @@
}
}
};
+
Model.loading = (async () => {
- let prefsNames = [
+ const prefsNames = [
"whitelist",
"blacklist",
"subject",
@@ -84,17 +88,17 @@
];
Model.prefs = await browser.storage.local.get(prefsNames.map(name => `pref_${name}`));
- for (let listName of LIST_NAMES) {
- let prefName = `pref_${listName}list`;
+ for (const listName of LIST_NAMES) {
+ const prefName = `pref_${listName}list`;
await (Model.lists[listName] = new ListStore(prefName, Storage.CSV))
.load(Model.prefs[prefName]);
}
})();
- var Controller = {
+ const Controller = {
init() {
- let widgetsRoot = this.root = document.getElementById("widgets");
- for (let widget of widgetsRoot.querySelectorAll('[id^="pref_"]')) {
+ const widgetsRoot = this.root = document.getElementById("widgets");
+ for (const widget of widgetsRoot.querySelectorAll('[id^="pref_"]')) {
if (widget.id in Model.lists) {
populateListUI(widget);
} else if (widget.id in Model.prefs) {
@@ -105,7 +109,7 @@
this.populateListUI();
this.syncAll();
- for (let ev in Listeners) {
+ for (const ev in Listeners) {
widgetsRoot.addEventListener(ev, Listeners[ev]);
}
document.getElementById("site").onfocus = e => {
@@ -126,7 +130,7 @@
},
async addSite(list) {
- let url = document.getElementById("site").value.trim();
+ const url = document.getElementById("site").value.trim();
if (url && !Model.malformedUrl(url)) {
await this.addToList(list, url);
@@ -138,7 +142,7 @@
this.syncAll();
},
async swapSelection(list) {
- let origin = list === Model.lists.black ? "white" : "black";
+ const origin = list === Model.lists.black ? "white" : "black";
await this.addToList(list, ...Array.prototype.map.call(
document.querySelectorAll(`select#${origin} option:checked`),
option => option.value)
@@ -151,15 +155,15 @@
},
syncSiteUI() {
- let widget = document.getElementById("site");
- let list2button = listName => document.getElementById(`cmd-${listName}list-site`);
+ const widget = document.getElementById("site");
+ const list2button = listName => document.getElementById(`cmd-${listName}list-site`);
- for (let bi of LIST_NAMES.map(list2button)) {
+ for (const bi of LIST_NAMES.map(list2button)) {
bi.disabled = true;
}
- let url = widget.value.trim();
- let malformedUrl = url && Model.malformedUrl(url);
+ const url = widget.value.trim();
+ const malformedUrl = url && Model.malformedUrl(url);
widget.classList.toggle("error", !!malformedUrl);
document.getElementById("site-error").textContent = malformedUrl || "";
if (!url) return;
@@ -167,8 +171,8 @@
widget.value = url;
}
- for (let listName of LIST_NAMES) {
- let list = Model.lists[listName];
+ for (const listName of LIST_NAMES) {
+ const list = Model.lists[listName];
if (!list.contains(url)) {
list2button(listName).disabled = false;
}
@@ -176,19 +180,18 @@
},
syncListsUI() {
- let total = 0;
- for (let id of ["black", "white"]) {
- let selected = document.querySelectorAll(`select#${id} option:checked`).length;
- let other = id === "black" ? "white" : "black";
+ const total = ["black", "white"].reduce((cum, id) => {
+ const selected = document.querySelectorAll(`select#${id} option:checked`).length;
+ const other = id === "black" ? "white" : "black";
document.getElementById(`cmd-${other}list`).disabled = selected === 0;
- total += selected;
- }
+ return cum + selected;
+ }, 0);
document.getElementById("cmd-delete").disabled = total === 0;
},
async deleteSelection() {
- for (let id of ["black", "white"]) {
- let selection = document.querySelectorAll(`select#${id} option:checked`);
+ for (const id of ["black", "white"]) {
+ const selection = document.querySelectorAll(`select#${id} option:checked`);
await Model.lists[id].remove(...Array.prototype.map.call(selection, option => option.value));
}
this.populateListUI();
@@ -197,16 +200,16 @@
populateListUI(widget) {
if (!widget) {
- for (let id of ["white", "black"]) {
+ for (const id of ["white", "black"]) {
this.populateListUI(document.getElementById(id));
}
return;
}
widget.innerHTML = "";
- let items = [...Model.lists[widget.id].items].sort();
- let options = new DocumentFragment();
- for (let item of items) {
- let option = document.createElement("option");
+ const items = [...Model.lists[widget.id].items].sort();
+ const options = new DocumentFragment();
+ for (const item of items) {
+ const option = document.createElement("option");
option.value = option.textContent = option.title = item;
options.appendChild(option);
}
@@ -214,7 +217,7 @@
}
};
- var KeyEvents = {
+ const KeyEvents = {
Delete(e) {
if (e.target.matches("#lists select")) {
Controller.deleteSelection();
@@ -227,7 +230,7 @@
},
KeyA(e) {
if (e.target.matches("select") && e.ctrlKey) {
- for (let o of e.target.options) {
+ for (const o of e.target.options) {
o.selected = true;
}
Controller.syncListsUI();
@@ -235,14 +238,14 @@
}
}
- var Listeners = {
+ const Listeners = {
async change(e) {
- let { target } = e;
- let { id } = target;
+ const { target } = e;
+ const { id } = target;
if (id in Model.lists) {
Controller.syncListsUI();
- let selection = target.querySelectorAll("option:checked");
+ const selection = target.querySelectorAll("option:checked");
if (selection.length === 1) {
document.getElementById("site").value = selection[0].value;
}
@@ -251,24 +254,25 @@
},
click(e) {
- let { target } = e;
+ const { target } = e;
- if (!/^cmd-(white|black|delete)(list-site)?/.test(target.id)) return;
+ const match = /^cmd-(white|black|delete)(list-site)?/.exec(target.id);
+ if (!match) return;
e.preventDefault();
- let cmd = RegExp.$1;
+ const cmd = match[1];
if (cmd === "delete") {
Controller.deleteSelection();
return;
}
- let list = Model.lists[cmd];
+ const list = Model.lists[cmd];
if (list) {
- Controller[RegExp.$2 ? "addSite" : "swapSelection"](list);
+ Controller[match[2] ? "addSite" : "swapSelection"](list);
return;
}
},
keypress(e) {
- let { code } = e;
+ const { code } = e;
if (code && typeof KeyEvents[code] === "function") {
if (KeyEvents[code](e) === false) {
e.preventDefault();
@@ -278,15 +282,15 @@
},
async input(e) {
- let { target } = e;
- let { id } = target;
+ const { target } = e;
+ const { id } = target;
if (!id) return;
if (id === "site") {
Controller.syncSiteUI();
- let url = target.value;
+ const url = target.value;
if (url) {
- let o = document.querySelector(`#lists select option[value="${url}"]`);
+ const o = document.querySelector(`#lists select option[value="${url}"]`);
if (o) {
o.scrollIntoView();
o.selected = true;
@@ -302,7 +306,7 @@
}
};
- window.addEventListener("DOMContentLoaded", async e => {
+ window.addEventListener("DOMContentLoaded", async _ => {
await Model.loading;
Controller.init();
});
diff --git a/test/spec/LibreJSSpec.js b/test/spec/LibreJSSpec.js
index 3ec75c5..5632e9f 100644
--- a/test/spec/LibreJSSpec.js
+++ b/test/spec/LibreJSSpec.js
@@ -283,7 +283,7 @@ describe('LibreJS\' components', () => {
});
});
- describe('Contact finder', () => {
+ describe('The contact finder', () => {
it('should display the contact finder iframe', async (done) => {
await browser.runtime.connect({ name: "port-from-cs" }).postMessage({ invoke_contact_finder: 1 });
// Direct await / async does not work as executeScript does not wait