CanvasBlocker/options/optionsGui.js

374 lines
11 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
(function(){
"use strict";
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
scope = {};
window.scope.optionsGui = scope;
}
const logging = require("./logging");
function createDescription(setting){
var c = document.createElement("div");
c.className = "content";
var title = document.createElement("span");
title.className = "title";
title.textContent = browser.i18n.getMessage(setting.name + "_title");
c.appendChild(title);
var descriptionText = browser.i18n.getMessage(setting.name + "_description");
if (descriptionText){
var info = document.createElement("div");
info.className = "info";
c.appendChild(info);
var description = document.createElement("div");
description.className = "description";
description.textContent = descriptionText;
info.appendChild(description);
}
return c;
}
function createSelect(setting){
var select = document.createElement("select");
select.dataset.type = typeof setting.defaultValue;
setting.options.forEach(function(value){
var option = document.createElement("option");
if (typeof value === typeof setting.defaultValue){
option.value = value;
if (setting.defaultValue === value){
option.selected = true;
}
option.text = browser.i18n.getMessage(setting.name + "_options." + value) || value;
}
else {
option.disabled = true;
option.text = "\u2500".repeat(20);
}
select.appendChild(option);
});
return select;
}
var inputTypes = {
number: {
input: function(input, value){
input.type = "number";
input.value = value;
return input;
},
updateCallback: function(input, value){
input.value = value;
return input.value;
},
getValue: function(input){
return parseFloat(input.value);
}
},
string: {
input: function(input, value){
input.type = "text";
input.value = value;
return input;
},
updateCallback: function(input, value){
input.value = value;
return input.value;
},
getValue: function(input){
return input.value;
}
},
boolean: {
input: function(input, value){
input.type = "checkbox";
input.checked = value;
input.style.display = "inline";
return input;
},
updateCallback: function(input, value){
input.checked = value;
return input.checked;
},
getValue: function(input){
return input.checked;
}
},
object: false
};
function createInput(setting, url = ""){
var type = inputTypes[typeof setting.defaultValue];
var input;
if (setting.options){
input = createSelect(setting);
}
else {
if (type){
input = document.createElement("input");
type.input(input, setting.defaultValue);
}
}
if (type){
setting.on(function(){type.updateCallback(input, setting.get(url));}, url);
input.addEventListener("change", function(){
var value = type.getValue(input);
setting.set(value, url);
logging.message("changed setting", setting.name, ":", value);
});
}
else if (setting.keys){
input = document.createElement("table");
setting.keys.forEach(function(key){
let row = document.createElement("tr");
if (typeof key === "object"){
let cell = document.createElement("td");
cell.colSpan = 2;
let h = document.createElement("h" + (2 + (key.level || 1)));
h.textContent = key.message? browser.i18n.getMessage(key.message): key.name;
cell.appendChild(h);
row.appendChild(cell);
input.appendChild(row);
return;
}
let nameCell = document.createElement("td");
nameCell.textContent = key;
row.appendChild(nameCell);
let keyType = inputTypes[typeof setting.defaultKeyValue];
let keyInput = document.createElement("input");
keyType.input(keyInput, setting.defaultKeyValue);
let inputCell = document.createElement("td");
inputCell.appendChild(keyInput);
row.appendChild(inputCell);
setting.on(function(){
var container = setting.get(url);
keyType.updateCallback(
keyInput,
container && container.hasOwnProperty(key)?
container[key]:
setting.defaultKeyValue,
url
);
});
keyInput.addEventListener("change", function(){
var value = keyType.getValue(keyInput);
var container = setting.get(url);
if (!container){
container = setting.defaultValue;
}
container[key] = value;
setting.set(container, url);
logging.message("changed setting", setting.name, "(", key, "):", value);
});
input.appendChild(row);
});
}
if (setting.urlSpecific && url === ""){
let container = document.createElement("div");
container.className = "urlValues collapsed";
container.appendChild(input);
var collapser = document.createElement("span");
collapser.classList.add("collapser");
container.appendChild(collapser);
collapser.addEventListener("click", function(){
container.classList.toggle("collapsed");
container.classList.toggle("expanded");
});
let urlTable = document.createElement("table");
let caption = document.createElement("caption");
caption.textContent = browser.i18n.getMessage(setting.urlContainer.name + "_title");
urlTable.appendChild(caption);
let body = document.createElement("tbody");
urlTable.appendChild(body);
let foot = document.createElement("tfoot");
let footRow = document.createElement("tr");
let footCell = document.createElement("td");
footCell.colSpan = 3;
let newInput = document.createElement("input");
newInput.title = browser.i18n.getMessage("inputURL");
footCell.appendChild(newInput);
let footPlus = document.createElement("span");
footPlus.classList.add("add");
footPlus.textContent = "+";
footPlus.addEventListener("click", function(){
var url = newInput.value.trim();
if (url){
setting.set(setting.get(url), url);
newInput.value = "";
}
});
footCell.appendChild(footPlus);
footRow.appendChild(footCell);
foot.appendChild(footRow);
urlTable.appendChild(foot);
container.appendChild(urlTable);
setting.urlContainer.on(function({newValue}){
body.innerHTML = "";
newValue.forEach(function(entry){
let row = document.createElement("tr");
let urlCell = document.createElement("td");
urlCell.classList.add("url");
urlCell.addEventListener("click", function(){
var input = document.createElement("input");
input.classList.add("urlInput");
input.style.width = urlCell.clientWidth + "px";
input.style.height = urlCell.clientHeight + "px";
urlCell.innerHTML = "";
urlCell.appendChild(input);
input.title = browser.i18n.getMessage("inputURL");
input.value = entry.url;
input.focus();
input.addEventListener("blur", function(){
var url = input.value.trim();
if (url){
entry.url = url;
setting.urlContainer.refresh();
}
urlCell.removeChild(input);
urlCell.textContent = entry.url;
});
});
urlCell.textContent = entry.url;
row.appendChild(urlCell);
let input = createInput(setting, entry.url);
type.updateCallback(input, setting.get(entry.url));
if (!entry.hasOwnProperty(setting.name)){
input.classList.add("notSpecifiedForUrl");
}
let inputCell = document.createElement("td");
inputCell.appendChild(input);
row.appendChild(inputCell);
let clearCell = document.createElement("td");
clearCell.className = "reset";
clearCell.textContent = "\xD7";
clearCell.addEventListener("click", function(){
setting.reset(entry.url);
});
row.appendChild(clearCell);
body.appendChild(row);
});
});
return container;
}
return input || document.createElement("span");
}
function createButton(setting){
var button = document.createElement("button");
button.textContent = browser.i18n.getMessage(setting.name + "_label");
button.addEventListener("click", setting.action);
return button;
}
function createInteraction(setting){
var c = document.createElement("div");
c.className = "content";
var interaction;
if (setting.action){
interaction = createButton(setting);
}
else if (setting.inputs){
interaction = document.createElement("span");
setting.inputs.forEach(function(inputSetting){
var input = createInput(inputSetting);
input.classList.add("multiple" + setting.inputs.length);
interaction.appendChild(input);
});
}
else {
interaction = createInput(setting);
}
interaction.classList.add("setting");
interaction.dataset.storageName = setting.name;
interaction.dataset.storageType = typeof setting.defaultValue;
c.appendChild(interaction);
return c;
}
function createHide(setting){
var label = document.createElement("label");
label.className = "content hideContent";
var input = document.createElement("input");
input.type = "checkbox";
input.className = "hide";
input.checked = setting.getHide();
input.addEventListener("change", function(){
setting.setHide(this.checked);
});
setting.onHideChange(function(value){
input.checked = value;
});
label.appendChild(input);
var display = document.createElement("span");
display.className = "display";
label.appendChild(display);
return label;
}
function createSettingRow(setting){
var tr = document.createElement("tr");
tr.className = "settingRow";
var hide = document.createElement("td");
hide.className = "hideColumn";
hide.appendChild(createHide(setting));
tr.appendChild(hide);
var left = document.createElement("td");
left.appendChild(createDescription(setting));
tr.appendChild(left);
var right = document.createElement("td");
right.appendChild(createInteraction(setting));
tr.appendChild(right);
return tr;
}
scope.createSettingRow = createSettingRow;
function createThead(displayHidden){
const tHead = document.createElement("thead");
const headRow = document.createElement("tr");
const hideHeadCell = document.createElement("td");
hideHeadCell.className = "hideColumn";
hideHeadCell.title = browser.i18n.getMessage(displayHidden.name + "_description");
const label = document.createElement("label");
const input = createInput(displayHidden);
input.className = "displayHidden";
label.appendChild(input);
const display = document.createElement("span");
display.className = "display";
label.appendChild(display);
hideHeadCell.appendChild(label);
headRow.appendChild(hideHeadCell);
const restHeadCell = document.createElement("td");
restHeadCell.colSpan = 2;
headRow.appendChild(restHeadCell);
tHead.appendChild(headRow);
return tHead;
}
scope.createThead = createThead;
}());