| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * A thin wrapper around a html element, which allows to generate a HTML-element. | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |  * Assumes a read-only configuration, so it has no 'ListenTo' | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export default abstract class BaseUIElement { | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |     protected _constructedHtmlElement: HTMLElement | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |     protected isDestroyed = false | 
					
						
							| 
									
										
										
										
											2022-08-22 13:34:47 +02:00
										 |  |  |     protected readonly clss: Set<string> = new Set<string>() | 
					
						
							|  |  |  |     protected style: string | 
					
						
							| 
									
										
										
										
											2022-08-22 19:16:37 +02:00
										 |  |  |     private _onClick: () => void | Promise<void> | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     public onClick(f: () => void) { | 
					
						
							|  |  |  |         this._onClick = f | 
					
						
							|  |  |  |         this.SetClass("clickable") | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |         if (this._constructedHtmlElement !== undefined) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             this._constructedHtmlElement.onclick = f | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return this | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     AttachTo(divId: string) { | 
					
						
							|  |  |  |         let element = document.getElementById(divId) | 
					
						
							|  |  |  |         if (element === null) { | 
					
						
							|  |  |  |             throw "SEVERE: could not attach UIElement to " + divId | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (element.firstChild) { | 
					
						
							|  |  |  |             //The list is LIVE so it will re-index each call
 | 
					
						
							|  |  |  |             element.removeChild(element.firstChild) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const el = this.ConstructElement() | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |         if (el !== undefined) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             element.appendChild(el) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |         return this | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-07-18 08:21:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public ScrollToTop() { | 
					
						
							|  |  |  |         this._constructedHtmlElement?.scrollTo(0, 0) | 
					
						
							| 
									
										
										
										
											2022-02-09 00:35:59 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-08-19 18:30:43 +02:00
										 |  |  |      * Adds all the relevant classes, space separated | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public SetClass(clss: string) { | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |         if (clss == undefined) { | 
					
						
							| 
									
										
										
										
											2022-04-13 02:44:06 +02:00
										 |  |  |             return this | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |         const all = clss.split(" ").map((clsName) => clsName.trim()) | 
					
						
							|  |  |  |         let recordedChange = false | 
					
						
							| 
									
										
										
										
											2021-06-12 02:58:32 +02:00
										 |  |  |         for (let c of all) { | 
					
						
							|  |  |  |             c = c.trim() | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             if (this.clss.has(clss)) { | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             if (c === undefined || c === "") { | 
					
						
							| 
									
										
										
										
											2021-06-12 02:58:32 +02:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             this.clss.add(c) | 
					
						
							|  |  |  |             recordedChange = true | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (recordedChange) { | 
					
						
							|  |  |  |             this._constructedHtmlElement?.classList.add(...Array.from(this.clss)) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return this | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-18 08:21:16 +00:00
										 |  |  |     public RemoveClass(classes: string): BaseUIElement { | 
					
						
							|  |  |  |         const all = classes.split(" ").map((clsName) => clsName.trim()) | 
					
						
							|  |  |  |         for (let clss of all) { | 
					
						
							|  |  |  |             if (this.clss.has(clss)) { | 
					
						
							|  |  |  |                 this.clss.delete(clss) | 
					
						
							|  |  |  |                 this._constructedHtmlElement?.classList.remove(clss) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         return this | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public HasClass(clss: string): boolean { | 
					
						
							| 
									
										
										
										
											2021-06-15 00:28:59 +02:00
										 |  |  |         return this.clss.has(clss) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public SetStyle(style: string): BaseUIElement { | 
					
						
							|  |  |  |         this.style = style | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |         if (this._constructedHtmlElement !== undefined) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             this._constructedHtmlElement.style.cssText = style | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return this | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * The same as 'Render', but creates a HTML element instead of the HTML representation | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public ConstructElement(): HTMLElement { | 
					
						
							| 
									
										
										
										
											2022-04-28 00:32:15 +02:00
										 |  |  |         if (typeof window === undefined) { | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             return undefined | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (this._constructedHtmlElement !== undefined) { | 
					
						
							|  |  |  |             return this._constructedHtmlElement | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 21:41:51 +02:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             const el = this.InnerConstructElement() | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             if (el === undefined) { | 
					
						
							|  |  |  |                 return undefined | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             this._constructedHtmlElement = el | 
					
						
							|  |  |  |             const style = this.style | 
					
						
							|  |  |  |             if (style !== undefined && style !== "") { | 
					
						
							|  |  |  |                 el.style.cssText = style | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-07-20 12:04:14 +02:00
										 |  |  |             if (this.clss?.size > 0) { | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |                 try { | 
					
						
							|  |  |  |                     el.classList.add(...Array.from(this.clss)) | 
					
						
							|  |  |  |                 } catch (e) { | 
					
						
							|  |  |  |                     console.error( | 
					
						
							|  |  |  |                         "Invalid class name detected in:", | 
					
						
							|  |  |  |                         Array.from(this.clss).join(" "), | 
					
						
							|  |  |  |                         "\nErr msg is ", | 
					
						
							|  |  |  |                         e | 
					
						
							|  |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             if (this._onClick !== undefined) { | 
					
						
							|  |  |  |                 const self = this | 
					
						
							| 
									
										
										
										
											2022-08-22 19:16:37 +02:00
										 |  |  |                 el.onclick = async (e) => { | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |                     // @ts-ignore
 | 
					
						
							|  |  |  |                     if (e.consumed) { | 
					
						
							|  |  |  |                         return | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-08-22 19:16:37 +02:00
										 |  |  |                     const v = self._onClick() | 
					
						
							|  |  |  |                     if (typeof v === "object") { | 
					
						
							|  |  |  |                         await v | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |                     // @ts-ignore
 | 
					
						
							|  |  |  |                     e.consumed = true | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-09-30 21:44:55 +02:00
										 |  |  |                 el.classList.add("pointer-events-none", "cursor-pointer") | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             return el | 
					
						
							|  |  |  |         } catch (e) { | 
					
						
							| 
									
										
										
										
											2021-06-16 14:23:53 +02:00
										 |  |  |             const domExc = e as DOMException | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |             if (domExc) { | 
					
						
							| 
									
										
										
										
											2022-10-27 01:50:01 +02:00
										 |  |  |                 console.error( | 
					
						
							|  |  |  |                     "An exception occured", | 
					
						
							|  |  |  |                     domExc.code, | 
					
						
							|  |  |  |                     domExc.message, | 
					
						
							|  |  |  |                     domExc.name, | 
					
						
							|  |  |  |                     domExc | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-06-16 14:23:53 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             console.error(e) | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public AsMarkdown(): string { | 
					
						
							| 
									
										
										
										
											2022-02-14 02:26:03 +01:00
										 |  |  |         throw "AsMarkdown is not implemented; implement it in the subclass" | 
					
						
							| 
									
										
										
										
											2021-06-15 00:28:59 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public Destroy() { | 
					
						
							| 
									
										
										
										
											2022-01-06 18:51:52 +01:00
										 |  |  |         this.isDestroyed = true | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-23 02:14:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     protected abstract InnerConstructElement(): HTMLElement | 
					
						
							| 
									
										
										
										
											2021-09-30 21:41:51 +02:00
										 |  |  | } |