2023-06-09 00:37:29 +02:00
|
|
|
class View extends HTMLElement {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this._model = null;
|
2023-06-09 02:03:57 +02:00
|
|
|
this._listener = () => this.render();
|
2023-06-10 13:08:08 +02:00
|
|
|
this._disableChangeEvent = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
get elements() {
|
|
|
|
const elements = this.querySelectorAll("[x-id]");
|
|
|
|
const result = {};
|
|
|
|
elements.forEach((element) => (result[element.getAttribute("x-id")] = element));
|
|
|
|
return result;
|
2023-06-09 00:37:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
set model(model) {
|
|
|
|
if (this._model) this._model.removeListener(this._listener);
|
|
|
|
this._model = model;
|
|
|
|
this._model.addListener(this._listener);
|
2023-06-10 13:08:08 +02:00
|
|
|
this.render();
|
|
|
|
}
|
|
|
|
|
|
|
|
get model() {
|
|
|
|
return this._model;
|
|
|
|
}
|
|
|
|
|
|
|
|
get state() {
|
|
|
|
const elements = this.elements;
|
|
|
|
const properties = ["checked", "value"];
|
|
|
|
const state = {};
|
|
|
|
for (const key of Object.keys(elements)) {
|
|
|
|
const element = elements[key];
|
|
|
|
if (!element.hasAttribute("x-state")) continue;
|
|
|
|
const elementState = {};
|
|
|
|
for (const property of properties) {
|
|
|
|
if (property in element) {
|
|
|
|
elementState[property] = element[property];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
state[key] = elementState;
|
|
|
|
}
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
set state(state) {
|
|
|
|
const elements = this.elements;
|
|
|
|
this._disableChangeEvent = true;
|
|
|
|
for (const key of Object.keys(elements)) {
|
|
|
|
const elementState = state[key];
|
|
|
|
if (elementState) {
|
|
|
|
const element = elements[key];
|
|
|
|
for (const property in elementState) {
|
|
|
|
element[property] = elementState[property];
|
|
|
|
if (element.localName === "input" && element.getAttribute("type") === "radio") {
|
|
|
|
const changeEvent = new CustomEvent("change", {
|
|
|
|
bubbles: true,
|
|
|
|
cancelable: true,
|
|
|
|
});
|
|
|
|
element.dispatchEvent(changeEvent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this._disableChangeEvent = false;
|
|
|
|
this.fireChangeEvent();
|
2023-06-09 00:37:29 +02:00
|
|
|
}
|
|
|
|
|
2023-06-09 02:03:57 +02:00
|
|
|
render() {}
|
2023-06-10 13:08:08 +02:00
|
|
|
|
|
|
|
setupEventHandlers() {
|
|
|
|
const handler = (event) => {
|
|
|
|
event.stopPropagation();
|
|
|
|
this.fireChangeEvent();
|
|
|
|
};
|
|
|
|
|
|
|
|
const elements = this.elements;
|
|
|
|
for (const key of Object.keys(elements)) {
|
|
|
|
const element = elements[key];
|
|
|
|
if (element.hasAttribute("x-change")) {
|
|
|
|
element.addEventListener("change", handler);
|
|
|
|
}
|
|
|
|
if (element.hasAttribute("x-click")) {
|
|
|
|
element.addEventListener("click", handler);
|
|
|
|
}
|
|
|
|
if (element.hasAttribute("x-input")) {
|
|
|
|
element.addEventListener("click", handler);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fireChangeEvent() {
|
|
|
|
if (this._disableChangeEvent) return;
|
|
|
|
const event = new CustomEvent("change", {
|
|
|
|
bubbles: true,
|
|
|
|
cancelable: true,
|
|
|
|
});
|
|
|
|
this.dispatchEvent(event);
|
|
|
|
}
|
2023-06-09 00:37:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.View = View;
|