.dungeon/module/components/incrementer.mjs
2024-04-04 20:02:19 -06:00

104 lines
2.6 KiB
JavaScript

/**
Attributes:
@property {number} value
@property {number} stepSize
@property {number} largeStepSize
*/
export class DotDungeonIncrementer extends HTMLElement {
static elementName = `dd-incrementer`;
static styles = ``;
#input;
#publicInput;
#sr;
constructor() {
super();
const value = this.getAttribute(`value`);
/*
This input exists for the sole purpose of making it so that the form data
works with this input without needing to do jank work arounds (even though
this on it's own is already a sort of jank work around).
*/
const hiddenInput = document.createElement(`input`);
hiddenInput.type = `hidden`;
hiddenInput.name = this.getAttribute(`name`);
hiddenInput.value = value;
this.#publicInput = hiddenInput;
this.appendChild(hiddenInput);
const sr = this.attachShadow({ mode: `open` });
this.#sr = sr;
const container = document.createElement(`div`);
if (DotDungeonIncrementer.styles) this.#embedStyles();
const input = document.createElement(`input`);
this.#input = input;
input.type = `number`;
input.addEventListener(`change`, this.#updateValue.bind(this));
input.value = value;
const increment = document.createElement(`button`);
increment.innerHTML = `+`;
increment.type = `button`;
increment.classList.value = `increment`;
increment.addEventListener(`click`, this.#increment.bind(this));
const decrement = document.createElement(`button`);
decrement.innerHTML = `-`;
decrement.type = `button`;
decrement.classList.value = `decrement`;
decrement.addEventListener(`click`, this.#decrement.bind(this));
// Construct the DOM
container.appendChild(decrement);
container.appendChild(input);
container.appendChild(increment);
sr.appendChild(container);
};
connectedCallback() {
if (!DotDungeonIncrementer.styles) {
fetch(`./systems/dotdungeon/.styles/components/incrementer.css`)
.then(r => r.text())
.then(t => {
DotDungeonIncrementer.styles = t;
this.#embedStyles();
});
};
};
#embedStyles() {
const style = document.createElement(`style`);
style.innerHTML = DotDungeonIncrementer.styles;
this.#sr.appendChild(style);
};
#updateValue() {
this.#publicInput.value = this.#input.value;
const event = new Event(`change`, { bubbles: true });
this.#publicInput.dispatchEvent(event);
};
#increment() {
this.#input.value++;
this.#updateValue();
};
#decrement() {
this.#input.value--;
this.#updateValue();
};
};
if (!window.customElements.get(DotDungeonIncrementer.elementName)) {
window.customElements.define(
DotDungeonIncrementer.elementName,
DotDungeonIncrementer
);
};