| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  | import {Utils} from "../Utils"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * 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; | 
					
						
							| 
									
										
										
										
											2021-06-10 01:36:20 +02:00
										 |  |  |     private clss: Set<string> = new Set<string>(); | 
					
						
							|  |  |  |     private style: string; | 
					
						
							|  |  |  |     private _onClick: () => void; | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +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-02-09 00:35:59 +01:00
										 |  |  |      | 
					
						
							|  |  |  |     public ScrollToTop(){ | 
					
						
							|  |  |  |         this._constructedHtmlElement?.scrollTo(0,0) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public RemoveClass(clss: string): BaseUIElement { | 
					
						
							|  |  |  |         if (this.clss.has(clss)) { | 
					
						
							|  |  |  |             this.clss.delete(clss); | 
					
						
							|  |  |  |             this._constructedHtmlElement?.classList.remove(clss) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         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 { | 
					
						
							|  |  |  |         if (Utils.runningFromConsole) { | 
					
						
							|  |  |  |             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 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (this.clss.size > 0) { | 
					
						
							|  |  |  |                 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; | 
					
						
							|  |  |  |                 el.onclick = (e) => { | 
					
						
							|  |  |  |                     // @ts-ignore
 | 
					
						
							|  |  |  |                     if (e.consumed) { | 
					
						
							|  |  |  |                         return; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     self._onClick(); | 
					
						
							|  |  |  |                     // @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) { | 
					
						
							|  |  |  |                 console.log("An exception occured", domExc.code, domExc.message, domExc.name) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } |