forked from MapComplete/MapComplete
		
	Refactoring: move all code files into a src directory
This commit is contained in:
		
							parent
							
								
									de99f56ca8
								
							
						
					
					
						commit
						e75d2789d2
					
				
					 389 changed files with 0 additions and 12 deletions
				
			
		
							
								
								
									
										135
									
								
								src/UI/Base/Table.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/UI/Base/Table.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,135 @@ | |||
| import BaseUIElement from "../BaseUIElement" | ||||
| import { Utils } from "../../Utils" | ||||
| import Translations from "../i18n/Translations" | ||||
| import { UIEventSource } from "../../Logic/UIEventSource" | ||||
| 
 | ||||
| export default class Table extends BaseUIElement { | ||||
|     private readonly _header: BaseUIElement[] | ||||
|     private readonly _contents: BaseUIElement[][] | ||||
|     private readonly _contentStyle: string[][] | ||||
|     private readonly _sortable: boolean | ||||
| 
 | ||||
|     constructor( | ||||
|         header: (BaseUIElement | string)[], | ||||
|         contents: (BaseUIElement | string)[][], | ||||
|         options?: { | ||||
|             contentStyle?: string[][] | ||||
|             sortable?: false | boolean | ||||
|         } | ||||
|     ) { | ||||
|         super() | ||||
|         this._contentStyle = options?.contentStyle ?? [["min-width: 9rem"]] | ||||
|         this._header = header?.map(Translations.W) | ||||
|         this._contents = contents.map((row) => row.map(Translations.W)) | ||||
|         this._sortable = options?.sortable ?? false | ||||
|     } | ||||
| 
 | ||||
|     AsMarkdown(): string { | ||||
|         const headerMarkdownParts = this._header.map((hel) => hel?.AsMarkdown() ?? " ") | ||||
|         const header = Utils.NoNull(headerMarkdownParts).join(" | ") | ||||
|         const headerSep = headerMarkdownParts.map((part) => "-".repeat(part.length + 2)).join(" | ") | ||||
|         const table = this._contents | ||||
|             .map((row) => row.map((el) => el?.AsMarkdown()?.replace("|", "\\|") ?? " ").join(" | ")) | ||||
|             .join("\n") | ||||
| 
 | ||||
|         return "\n\n" + [header, headerSep, table, ""].join("\n") | ||||
|     } | ||||
| 
 | ||||
|     protected InnerConstructElement(): HTMLElement { | ||||
|         const table = document.createElement("table") | ||||
| 
 | ||||
|         /** | ||||
|          * Sortmode: i: sort column i ascending; | ||||
|          * if i is negative : sort column (-i - 1) descending | ||||
|          */ | ||||
|         const sortmode = new UIEventSource<number>(undefined) | ||||
|         const self = this | ||||
|         const headerElems = Utils.NoNull( | ||||
|             (this._header ?? []).map((elem, i) => { | ||||
|                 if (self._sortable) { | ||||
|                     elem.onClick(() => { | ||||
|                         const current = sortmode.data | ||||
|                         if (current == i) { | ||||
|                             sortmode.setData(-1 - i) | ||||
|                         } else { | ||||
|                             sortmode.setData(i) | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
|                 return elem.ConstructElement() | ||||
|             }) | ||||
|         ) | ||||
|         if (headerElems.length > 0) { | ||||
|             const thead = document.createElement("thead") | ||||
| 
 | ||||
|             const tr = document.createElement("tr") | ||||
|             headerElems.forEach((headerElem) => { | ||||
|                 const td = document.createElement("th") | ||||
|                 td.appendChild(headerElem) | ||||
|                 tr.appendChild(td) | ||||
|             }) | ||||
|             thead.appendChild(tr) | ||||
|             table.appendChild(thead) | ||||
|         } | ||||
| 
 | ||||
|         for (let i = 0; i < this._contents.length; i++) { | ||||
|             let row = this._contents[i] | ||||
|             const tr = document.createElement("tr") | ||||
|             for (let j = 0; j < row.length; j++) { | ||||
|                 try { | ||||
|                     let elem = row[j] | ||||
|                     if (elem?.ConstructElement === undefined) { | ||||
|                         continue | ||||
|                     } | ||||
|                     const htmlElem = elem?.ConstructElement() | ||||
|                     if (htmlElem === undefined) { | ||||
|                         continue | ||||
|                     } | ||||
| 
 | ||||
|                     let style = undefined | ||||
|                     if ( | ||||
|                         this._contentStyle !== undefined && | ||||
|                         this._contentStyle[i] !== undefined && | ||||
|                         this._contentStyle[j] !== undefined | ||||
|                     ) { | ||||
|                         style = this._contentStyle[i][j] | ||||
|                     } | ||||
| 
 | ||||
|                     const td = document.createElement("td") | ||||
|                     td.style.cssText = style | ||||
|                     td.appendChild(htmlElem) | ||||
|                     tr.appendChild(td) | ||||
|                 } catch (e) { | ||||
|                     console.error("Could not render an element in a table due to", e, row[j]) | ||||
|                 } | ||||
|             } | ||||
|             table.appendChild(tr) | ||||
|         } | ||||
| 
 | ||||
|         sortmode.addCallback((sortCol) => { | ||||
|             if (sortCol === undefined) { | ||||
|                 return | ||||
|             } | ||||
|             const descending = sortCol < 0 | ||||
|             const col = descending ? -sortCol - 1 : sortCol | ||||
|             let rows: HTMLTableRowElement[] = Array.from(table.rows) | ||||
|             rows.splice(0, 1) // remove header row
 | ||||
|             rows = rows.sort((a, b) => { | ||||
|                 const ac = a.cells[col]?.textContent?.toLowerCase() | ||||
|                 const bc = b.cells[col]?.textContent?.toLowerCase() | ||||
|                 if (ac === bc) { | ||||
|                     return 0 | ||||
|                 } | ||||
|                 return ac < bc !== descending ? -1 : 1 | ||||
|             }) | ||||
|             for (let j = rows.length; j > 1; j--) { | ||||
|                 table.deleteRow(j) | ||||
|             } | ||||
|             for (const row of rows) { | ||||
|                 table.appendChild(row) | ||||
|             } | ||||
|         }) | ||||
| 
 | ||||
|         return table | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue