mapcomplete/UI/UIElement.ts

119 lines
3 KiB
TypeScript
Raw Normal View History

import {UIEventSource} from "../Logic/UIEventSource";
2021-06-10 01:36:20 +02:00
import BaseUIElement from "./BaseUIElement";
2020-06-24 00:35:19 +02:00
2021-06-10 01:36:20 +02:00
export abstract class UIElement extends BaseUIElement{
2020-09-02 11:37:34 +02:00
2020-06-24 00:35:19 +02:00
private static nextId: number = 0;
public readonly id: string;
public readonly _source: UIEventSource<any>;
2021-06-10 01:36:20 +02:00
2020-09-09 18:42:13 +02:00
private lastInnerRender: string;
2020-06-24 00:35:19 +02:00
protected constructor(source: UIEventSource<any> = undefined) {
2021-06-10 01:36:20 +02:00
super()
this.id = `ui-${this.constructor.name}-${UIElement.nextId}`;
2020-06-24 00:35:19 +02:00
this._source = source;
UIElement.nextId++;
this.ListenTo(source);
}
2020-07-08 13:12:23 +02:00
public ListenTo(source: UIEventSource<any>) {
2020-07-01 02:12:33 +02:00
if (source === undefined) {
2020-07-21 01:37:48 +02:00
return this;
2020-06-24 00:35:19 +02:00
}
const self = this;
source.addCallback(() => {
2020-09-09 18:42:13 +02:00
self.lastInnerRender = undefined;
2021-06-10 01:36:20 +02:00
if(self._constructedHtmlElement !== undefined){
self.UpdateElement(self._constructedHtmlElement);
}
2020-06-24 00:35:19 +02:00
})
2020-07-21 01:37:48 +02:00
return this;
2020-06-24 00:35:19 +02:00
}
2020-09-02 11:37:34 +02:00
2020-06-24 00:35:19 +02:00
Update(): void {
2020-07-20 09:57:19 +02:00
2020-09-12 23:15:17 +02:00
}
2021-06-10 01:36:20 +02:00
Render(): string {
return "Don't use Render!"
}
2020-09-12 23:15:17 +02:00
2021-06-10 01:36:20 +02:00
public InnerRenderAsString(): string {
let rendered = this.InnerRender();
if (typeof rendered !== "string") {
let html = rendered.ConstructElement()
return html.innerHTML
2020-09-12 23:15:17 +02:00
}
2021-06-10 01:36:20 +02:00
return rendered
2020-06-24 00:35:19 +02:00
}
2021-06-10 01:36:20 +02:00
public IsEmpty(): boolean {
return this.InnerRender() === undefined || this.InnerRender() === "";
2020-06-24 00:35:19 +02:00
}
2020-07-20 09:57:19 +02:00
/**
2021-06-10 01:36:20 +02:00
* Should be overridden for specific HTML functionality
*/
2021-06-10 01:36:20 +02:00
protected InnerConstructElement(): HTMLElement {
// Uses the old fashioned way to construct an element using 'InnerRender'
const innerRender = this.InnerRender();
if (innerRender === undefined || innerRender === "") {
return undefined;
}
const el = document.createElement("span")
if (typeof innerRender === "string") {
el.innerHTML = innerRender
} else {
const subElement = innerRender.ConstructElement();
if (subElement === undefined) {
return undefined;
}
2021-06-10 01:36:20 +02:00
el.appendChild(subElement)
}
2021-06-10 01:36:20 +02:00
return el;
}
2021-06-10 01:36:20 +02:00
protected UpdateElement(el: HTMLElement) : void{
const innerRender = this.InnerRender();
2021-01-06 02:21:50 +01:00
2021-06-10 01:36:20 +02:00
if (typeof innerRender === "string") {
if(el.innerHTML !== innerRender){
el.innerHTML = innerRender
}
} else {
const subElement = innerRender.ConstructElement();
if(el.children.length === 1 && el.children[0] === subElement){
return; // Nothing changed
}
2021-01-06 02:21:50 +01:00
2021-06-10 01:36:20 +02:00
while (el.firstChild) {
el.removeChild(el.firstChild);
}
if (subElement === undefined) {
return;
2021-01-06 02:21:50 +01:00
}
2021-06-10 01:36:20 +02:00
el.appendChild(subElement)
2021-01-06 02:21:50 +01:00
}
2021-06-10 01:36:20 +02:00
2021-01-06 02:21:50 +01:00
}
2021-06-10 01:36:20 +02:00
/**
* @deprecated The method should not be used
*/
protected abstract InnerRender(): string | BaseUIElement;
2020-07-20 15:54:50 +02:00
}
2020-06-24 00:35:19 +02:00
2020-07-29 15:05:19 +02:00