165 lines
4.9 KiB
JavaScript
165 lines
4.9 KiB
JavaScript
function optionGenericGet() {
|
|
return this.el.querySelector('input').value;
|
|
}
|
|
function optionGenericSet(value) {
|
|
this.el.querySelector('input').value = value;
|
|
}
|
|
function optionEnumGet() {
|
|
return this.el.querySelector('select').value;
|
|
}
|
|
function optionEnumSet(value) {
|
|
this.el.querySelector('select').value = value;
|
|
}
|
|
function optionBoolGet() {
|
|
return this.el.querySelector('input').checked;
|
|
}
|
|
function optionBoolSet(value) {
|
|
this.el.querySelector('input').checked = value;
|
|
}
|
|
function optionNumberGet() {
|
|
let value = (this.float === true ? parseFloat : parseInt)(
|
|
this.el.querySelector('input').value,
|
|
);
|
|
if (Number.isNaN(value) || typeof value !== 'number') value = 0;
|
|
if (typeof this.min === 'number') value = Math.max(value, this.min);
|
|
if (typeof this.max === 'number') value = Math.min(value, this.max);
|
|
return value;
|
|
}
|
|
function optionNumberSet(value) {
|
|
this.el.querySelector('input').value = value;
|
|
}
|
|
|
|
const allOptions = [];
|
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
|
|
function inflateOptions(optionsSchema) {
|
|
const booleanOption = document.querySelector('#boolean_option.templ');
|
|
const enumOption = document.querySelector('#enum_option.templ');
|
|
const textOption = document.querySelector('#text_option.templ');
|
|
const numberOption = document.querySelector('#number_option.templ');
|
|
const colorOption = document.querySelector('#color_option.templ');
|
|
|
|
function copyOver({ children }) {
|
|
while (children.length > 0) document.body.append(children[0]);
|
|
}
|
|
|
|
optionsSchema.forEach(option => {
|
|
let el;
|
|
option.get = optionGenericGet.bind(option);
|
|
option.set = optionGenericSet.bind(option);
|
|
|
|
switch (option.type) {
|
|
case 'boolean':
|
|
el = booleanOption.cloneNode(true);
|
|
option.get = optionBoolGet.bind(option);
|
|
option.set = optionBoolSet.bind(option);
|
|
break;
|
|
|
|
case 'enum':
|
|
el = enumOption.cloneNode(true);
|
|
option.enum.forEach(varriant => {
|
|
const optionEl = document.createElement('option');
|
|
optionEl.innerText = varriant;
|
|
optionEl.value = varriant;
|
|
el.querySelector('select').appendChild(optionEl);
|
|
});
|
|
option.get = optionEnumGet.bind(option);
|
|
option.set = optionEnumSet.bind(option);
|
|
break;
|
|
|
|
case 'text':
|
|
el = textOption.cloneNode(true);
|
|
break;
|
|
|
|
case 'number':
|
|
el = numberOption.cloneNode(true);
|
|
if (option.float === true)
|
|
el.querySelector('input').setAttribute('step', '0.001');
|
|
option.get = optionNumberGet.bind(option);
|
|
option.set = optionNumberSet.bind(option);
|
|
if (typeof option.min === 'number')
|
|
el.querySelector('input').setAttribute('min', option.min.toString());
|
|
if (typeof option.max === 'number')
|
|
el.querySelector('input').setAttribute('max', option.max.toString());
|
|
break;
|
|
|
|
case 'color':
|
|
el = colorOption.cloneNode(true);
|
|
break;
|
|
|
|
default:
|
|
throw new Error(`Unknown option type ${option.type}`);
|
|
}
|
|
|
|
el.querySelector('.title').innerText = option.name;
|
|
el.querySelector('.desc').innerText = option.description;
|
|
[option.el] = el.children;
|
|
copyOver(el);
|
|
allOptions.push(option);
|
|
});
|
|
}
|
|
|
|
function getItem(json, path) {
|
|
const mypath = path[0];
|
|
if (path.length === 1) return json[mypath];
|
|
if (json[mypath] != null) return getItem(json[mypath], path.slice(1));
|
|
return null;
|
|
}
|
|
function setItem(json, path, item) {
|
|
const mypath = path[0];
|
|
if (path.length === 1) json[mypath] = item;
|
|
else {
|
|
if (json[mypath] == null) json[mypath] = {};
|
|
setItem(json[mypath], path.slice(1), item);
|
|
}
|
|
}
|
|
|
|
window.loadOptions = config => {
|
|
allOptions.forEach(option => {
|
|
let value = getItem(config, option.path);
|
|
if (option.nullable === true && option.type === 'text' && value == null)
|
|
value = null;
|
|
else if (
|
|
option.nullable === true &&
|
|
option.type === 'number' &&
|
|
value == null
|
|
)
|
|
value = -1;
|
|
else if (value == null) return;
|
|
if (option.json === true && option.type === 'text')
|
|
value = JSON.stringify(value);
|
|
option.set(value);
|
|
option.el.classList.remove('unbounded');
|
|
});
|
|
};
|
|
|
|
if (window.top === window)
|
|
// eslint-disable-next-line no-alert
|
|
alert(
|
|
'Error: Page is top level. This page is supposed to be accessed from inside WeTTY.',
|
|
);
|
|
|
|
function saveConfig() {
|
|
const newConfig = {};
|
|
allOptions.forEach(option => {
|
|
let newValue = option.get();
|
|
if (
|
|
option.nullable === true &&
|
|
((option.type === 'text' && newValue === '') ||
|
|
(option.type === 'number' && newValue < 0))
|
|
)
|
|
return;
|
|
if (option.json === true && option.type === 'text')
|
|
newValue = JSON.parse(newValue);
|
|
setItem(newConfig, option.path, newValue);
|
|
});
|
|
window.wetty_save_config(newConfig);
|
|
}
|
|
|
|
window.addEventListener('input', () => {
|
|
const els = document.querySelectorAll('input, select');
|
|
for (let i = 0; i < els.length; i += 1) {
|
|
els[i].addEventListener('input', saveConfig);
|
|
}
|
|
});
|