| 
									
										
										
										
											2020-08-17 17:23:15 +02:00
										 |  |  | import {UIEventSource} from "../Logic/UIEventSource"; | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  | import {Utils} from "../Utils"; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  | export abstract class UIElement extends UIEventSource<string> { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     private static nextId: number = 0; | 
					
						
							|  |  |  |     public readonly id: string; | 
					
						
							|  |  |  |     public readonly _source: UIEventSource<any>; | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  |     public dumbMode = false; | 
					
						
							| 
									
										
										
										
											2021-01-18 02:51:42 +01:00
										 |  |  |     private clss: Set<string> = new Set<string>(); | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |     private style: string; | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |     private _hideIfEmpty = false; | 
					
						
							| 
									
										
										
										
											2020-09-09 18:42:13 +02:00
										 |  |  |     private lastInnerRender: string; | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  |     private _onClick: () => void; | 
					
						
							|  |  |  |     private _onHover: UIEventSource<boolean>; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  |     protected constructor(source: UIEventSource<any> = undefined) { | 
					
						
							| 
									
										
										
										
											2020-07-27 01:19:38 +02:00
										 |  |  |         super(""); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         this.id = "ui-element-" + UIElement.nextId; | 
					
						
							|  |  |  |         this._source = source; | 
					
						
							|  |  |  |         UIElement.nextId++; | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |         this.dumbMode = true; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         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
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         this.dumbMode = false; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         const self = this; | 
					
						
							|  |  |  |         source.addCallback(() => { | 
					
						
							| 
									
										
										
										
											2020-09-09 18:42:13 +02:00
										 |  |  |             self.lastInnerRender = undefined; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |             self.Update(); | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2020-07-21 01:37:48 +02:00
										 |  |  |         return this; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |     public onClick(f: (() => void)) { | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         this.dumbMode = false; | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |         this._onClick = f; | 
					
						
							| 
									
										
										
										
											2020-08-27 18:44:16 +02:00
										 |  |  |         this.SetClass("clickable") | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |         this.Update(); | 
					
						
							| 
									
										
										
										
											2020-07-01 17:38:48 +02:00
										 |  |  |         return this; | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public IsHovered(): UIEventSource<boolean> { | 
					
						
							|  |  |  |         this.dumbMode = false; | 
					
						
							|  |  |  |         if (this._onHover !== undefined) { | 
					
						
							|  |  |  |             return this._onHover; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Note: we just save it. 'Update' will register that an eventsource exist and install the necessary hooks
 | 
					
						
							|  |  |  |         this._onHover = new UIEventSource<boolean>(false); | 
					
						
							|  |  |  |         return this._onHover; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     Update(): void { | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  |         if (Utils.runningFromConsole) { | 
					
						
							| 
									
										
										
										
											2020-07-26 02:01:34 +02:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2020-07-25 18:00:08 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |         let element = document.getElementById(this.id); | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         if (element === undefined || element === null) { | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |             // The element is not painted or, in the case of 'dumbmode' this UI-element is not explicitely present
 | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |             if (this.dumbMode) { | 
					
						
							|  |  |  |                 // We update all the children anyway
 | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |                 this.UpdateAllChildren(); | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-10 21:06:56 +02:00
										 |  |  |         const newRender = this.InnerRender(); | 
					
						
							|  |  |  |         if (newRender !== this.lastInnerRender) { | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |             this.lastInnerRender = newRender; | 
					
						
							| 
									
										
										
										
											2020-09-10 21:06:56 +02:00
										 |  |  |             this.setData(this.InnerRender()); | 
					
						
							|  |  |  |             element.innerHTML = this.data; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |         if (this._hideIfEmpty) { | 
					
						
							|  |  |  |             if (element.innerHTML === "") { | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |                 element.parentElement.style.display = "none"; | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2020-09-03 16:44:48 +02:00
										 |  |  |                 element.parentElement.style.display = "block"; | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (this._onClick !== undefined) { | 
					
						
							|  |  |  |             const self = this; | 
					
						
							| 
									
										
										
										
											2020-07-22 12:17:06 +02:00
										 |  |  |             element.onclick = (e) => { | 
					
						
							| 
									
										
										
										
											2020-07-24 15:22:28 +02:00
										 |  |  |                 // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  |                 if (e.consumed) { | 
					
						
							| 
									
										
										
										
											2020-07-22 12:17:06 +02:00
										 |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |                 self._onClick(); | 
					
						
							| 
									
										
										
										
											2020-07-24 15:22:28 +02:00
										 |  |  |                 // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2020-07-22 12:17:06 +02:00
										 |  |  |                 e.consumed = true; | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-01 21:21:29 +02:00
										 |  |  |             element.style.pointerEvents = "all"; | 
					
						
							| 
									
										
										
										
											2020-07-01 02:12:33 +02:00
										 |  |  |             element.style.cursor = "pointer"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         if (this._onHover !== undefined) { | 
					
						
							|  |  |  |             const self = this; | 
					
						
							|  |  |  |             element.addEventListener('mouseover', () => self._onHover.setData(true)); | 
					
						
							|  |  |  |             element.addEventListener('mouseout', () => self._onHover.setData(false)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         this.InnerUpdate(element); | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |         this.UpdateAllChildren(); | 
					
						
							| 
									
										
										
										
											2020-07-20 09:57:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 23:39:31 +01:00
										 |  |  |     HideOnEmpty(hide: boolean): UIElement { | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         this._hideIfEmpty = hide; | 
					
						
							|  |  |  |         this.Update(); | 
					
						
							|  |  |  |         return this; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     Render(): string { | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |         this.lastInnerRender = this.InnerRender(); | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         if (this.dumbMode) { | 
					
						
							| 
									
										
										
										
											2020-09-09 18:42:13 +02:00
										 |  |  |             return this.lastInnerRender; | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         let style = ""; | 
					
						
							|  |  |  |         if (this.style !== undefined && this.style !== "") { | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |             style = `style="${this.style}" `; | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-09-13 00:53:24 +02:00
										 |  |  |         let clss = ""; | 
					
						
							| 
									
										
										
										
											2021-01-18 02:51:42 +01:00
										 |  |  |         if (this.clss.size > 0) { | 
					
						
							|  |  |  |             clss = `class='${Array.from(this.clss).join(" ")}' `; | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         return `<span ${clss}${style}id='${this.id}'>${this.lastInnerRender}</span>` | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     AttachTo(divId: string) { | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         this.dumbMode = false; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         let element = document.getElementById(divId); | 
					
						
							| 
									
										
										
										
											2020-07-20 09:57:19 +02:00
										 |  |  |         if (element === null) { | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |             throw "SEVERE: could not attach UIElement to " + divId; | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         element.innerHTML = this.Render(); | 
					
						
							|  |  |  |         this.Update(); | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |         return this; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 18:24:00 +02:00
										 |  |  |     public abstract InnerRender(): string; | 
					
						
							| 
									
										
										
										
											2020-07-20 09:57:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     public IsEmpty(): boolean { | 
					
						
							|  |  |  |         return this.InnerRender() === ""; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-22 18:57:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public SetClass(clss: string): UIElement { | 
					
						
							| 
									
										
										
										
											2021-01-18 02:51:42 +01:00
										 |  |  |         return this.AddClass(clss); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Adds all the relevant classes, space seperated | 
					
						
							|  |  |  |      * @param clss | 
					
						
							|  |  |  |      * @constructor | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public AddClass(clss: string) { | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         this.dumbMode = false; | 
					
						
							| 
									
										
										
										
											2021-01-18 02:51:42 +01:00
										 |  |  |         const all = clss.split(" "); | 
					
						
							|  |  |  |         let recordedChange = false; | 
					
						
							|  |  |  |         for (const c of all) { | 
					
						
							|  |  |  |             if (this.clss.has(clss)) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             this.clss.add(c); | 
					
						
							|  |  |  |             recordedChange = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (recordedChange) { | 
					
						
							| 
									
										
										
										
											2020-09-12 23:15:17 +02:00
										 |  |  |             this.Update(); | 
					
						
							| 
									
										
										
										
											2020-08-27 18:44:16 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  |         return this; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-01 01:23:45 +02:00
										 |  |  |     public RemoveClass(clss: string): UIElement { | 
					
						
							| 
									
										
										
										
											2021-01-18 02:51:42 +01:00
										 |  |  |         if (this.clss.has(clss)) { | 
					
						
							|  |  |  |             this.clss.delete(clss); | 
					
						
							| 
									
										
										
										
											2020-10-01 01:23:45 +02:00
										 |  |  |             this.Update(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return this; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |     public SetStyle(style: string): UIElement { | 
					
						
							|  |  |  |         this.dumbMode = false; | 
					
						
							|  |  |  |         this.style = style; | 
					
						
							| 
									
										
										
										
											2020-08-31 02:59:47 +02:00
										 |  |  |         this.Update(); | 
					
						
							| 
									
										
										
										
											2020-08-22 18:57:27 +02:00
										 |  |  |         return this; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-01-06 02:21:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Called after the HTML has been replaced. Can be used for css tricks
 | 
					
						
							|  |  |  |     protected InnerUpdate(htmlElement: HTMLElement) { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private UpdateAllChildren() { | 
					
						
							|  |  |  |         for (const i in this) { | 
					
						
							|  |  |  |             const child = this[i]; | 
					
						
							|  |  |  |             if (child instanceof UIElement) { | 
					
						
							|  |  |  |                 child.Update(); | 
					
						
							|  |  |  |             } else if (child instanceof Array) { | 
					
						
							|  |  |  |                 for (const ch of child) { | 
					
						
							|  |  |  |                     if (ch instanceof UIElement) { | 
					
						
							|  |  |  |                         ch.Update(); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-29 15:05:19 +02:00
										 |  |  | 
 |