Files
packager/parseoptions.js
T

169 lines
4.0 KiB
JavaScript

/*
Copyright (c) 2020 Thomas Weber
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
window.O = (function() {
const options = Object.create(null);
const setOption = (name, value) => {
// name supports "a.b.c" syntax
const parts = name.split('.');
const last = parts.pop();
let target = options;
for (const part of parts) {
if (typeof target[part] === 'undefined') {
target[part] = Object.create(null);
}
target = target[part];
}
target[last] = value;
};
const onchange = (e) => {
const target = e.target;
const name = target.name;
const value = getValue(target);
setOption(name, value);
setLocalValue(name, value);
if (options.onchange) {
options.onchange();
}
};
const getValue = (el) => {
const tag = el.tagName.toLowerCase();
if (tag === 'select') {
return el.value;
}
if (tag === 'textarea') {
return el.value;
}
if (tag === 'input') {
switch (el.type) {
case 'number':
return +el.value;
case 'text':
case 'radio':
return el.value;
case 'checkbox':
return el.checked;
case 'file':
return el.files[0] || null;
}
}
};
const setValue = (el, value) => {
const tag = el.tagName.toLowerCase();
if (tag === 'select') {
el.value = value;
}
if (tag === 'textarea') {
el.value = value;
}
if (tag === 'input') {
switch (el.type) {
case 'text':
case 'number':
el.value = value;
break;
case 'radio':
el.checked = el.value === value;
break;
case 'checkbox':
el.checked = value;
break;
}
}
};
/**
* Returns all possible values for an HTML element
* @returns {string[]|null} list of possible values, or null if all values are possible
*/
const getPossibleValues = (el) => {
const tag = el.tagName.toLowerCase();
if (tag === 'select') {
return Array.from(el.options).map(i => i.value)
}
if (tag === 'input' && el.type === 'radio') {
return Array.from(document.getElementsByName(el.name)).map(i => i.value);
}
return null;
};
const setLocalValue = (name, value) => {
try {
localStorage.setItem(`opt:${name}`, JSON.stringify(value));
} catch (e) {
// ignore
}
};
const getLocalValue = (name) => {
try {
const v = localStorage.getItem(`opt:${name}`);
if (v !== null) {
return JSON.parse(v);
}
} catch (e) {
// ignore
}
return null;
};
const inputs = document.querySelectorAll('input, select, textarea');
for (const input of inputs) {
const name = input.name;
if (!name) continue;
const defaultValue = getValue(input);
const localValue = getLocalValue(name);
const possibleValues = getPossibleValues(input);
let value = defaultValue;
if (typeof value !== 'object' && localValue !== null && typeof localValue === typeof value) {
if (possibleValues === null || possibleValues.includes(localValue)) {
value = localValue;
setValue(input, value);
}
}
input.addEventListener('change', onchange);
const isRadio = input.tagName.toLowerCase() === 'input' && input.type === 'radio';
if (isRadio) {
if (input.checked) {
setOption(name, value);
}
} else {
setOption(name, value);
}
};
return options;
}());