93 lines
1.9 KiB
JavaScript
93 lines
1.9 KiB
JavaScript
import * as time from './time';
|
|
|
|
class InvalidInputError extends Error {
|
|
constructor(problems) {
|
|
super(`Invalid input: ${problems.join(', ')}`);
|
|
this.problems = problems;
|
|
}
|
|
}
|
|
|
|
class Deriver {
|
|
constructor(output, inputs, notice=null) {
|
|
this.output = output;
|
|
this.inputs = inputs;
|
|
this.notice = notice;
|
|
}
|
|
|
|
get values() {
|
|
return this.inputs.map(input => input.value);
|
|
}
|
|
|
|
bind() {
|
|
this.inputs.forEach(input => {
|
|
input.addEventListener('input', () => {
|
|
this.update();
|
|
});
|
|
});
|
|
}
|
|
|
|
update() {
|
|
try {
|
|
const output = this.derive();
|
|
this.output.value = output;
|
|
this.showError();
|
|
} catch (e) {
|
|
console.error(e);
|
|
this.showError(e);
|
|
}
|
|
}
|
|
|
|
showError(error='') {
|
|
if (!this.notice) {
|
|
return;
|
|
}
|
|
let message = error.message || error.toString();
|
|
if (Array.isArray(error.problems)) {
|
|
message = 'Invalid input: ' + error.problems.join(', ');
|
|
}
|
|
this.notice.innerText = message;
|
|
}
|
|
}
|
|
|
|
class DurationDeriver extends Deriver {
|
|
derive() {
|
|
const [ number, units ] = this.values;
|
|
const n = parseInt(number, 10);
|
|
if (!isFinite(n)) {
|
|
throw new InvalidInputError([`provided duration is not a number`]);
|
|
}
|
|
switch (units) {
|
|
case 's':
|
|
return n * time.SECOND;
|
|
case 'm':
|
|
return n * time.MINUTE;
|
|
case 'h':
|
|
return n * time.HOUR;
|
|
case 'd':
|
|
return n * 24 * time.HOUR;
|
|
}
|
|
throw new InvalidInputError([`unit ${units} is not valid`]);
|
|
}
|
|
}
|
|
|
|
const derivers = {
|
|
duration: DurationDeriver,
|
|
};
|
|
|
|
const deriveInputs = document.querySelectorAll('[data-derive]');
|
|
deriveInputs.forEach(deriveInput => {
|
|
|
|
const [ type, ...inputNames ] = deriveInput.dataset.derive.split(',');
|
|
if (!type in derivers) {
|
|
return;
|
|
}
|
|
|
|
const inputs = inputNames.map(inputName => document.querySelector(`[name="${inputName}"]`));
|
|
const notice = document.querySelector(deriveInput.dataset.deriveNotice);
|
|
|
|
const deriver = new derivers[type](deriveInput, inputs, notice);
|
|
deriver.bind();
|
|
deriver.update();
|
|
|
|
});
|