| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  | import {InputElement} from "./InputElement"; | 
					
						
							|  |  |  | import {UIEventSource} from "../../Logic/UIEventSource"; | 
					
						
							|  |  |  | import {UIElement} from "../UIElement"; | 
					
						
							|  |  |  | import Combine from "../Base/Combine"; | 
					
						
							|  |  |  | import {SubtleButton} from "../Base/SubtleButton"; | 
					
						
							| 
									
										
										
										
											2020-11-06 01:58:26 +01:00
										 |  |  | import Svg from "../../Svg"; | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class MultiInput<T> extends InputElement<T[]> { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private readonly _value: UIEventSource<T[]>; | 
					
						
							|  |  |  |     IsSelected: UIEventSource<boolean>; | 
					
						
							|  |  |  |     private elements: UIElement[] = []; | 
					
						
							|  |  |  |     private inputELements: InputElement<T>[] = []; | 
					
						
							|  |  |  |     private addTag: UIElement; | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |     private _options: { allowMovement?: boolean }; | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         addAElement: string, | 
					
						
							|  |  |  |         newElement: (() => T), | 
					
						
							|  |  |  |         createInput: (() => InputElement<T>), | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |         value: UIEventSource<T[]> = undefined, | 
					
						
							|  |  |  |         options?: { | 
					
						
							|  |  |  |             allowMovement?: boolean | 
					
						
							|  |  |  |         }) { | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         super(undefined); | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |         this._value = value ?? new UIEventSource<T[]>([]); | 
					
						
							|  |  |  |         value = this._value; | 
					
						
							| 
									
										
										
										
											2020-09-14 20:16:03 +02:00
										 |  |  |         this.ListenTo(value.map((latest : T[]) => latest.length)); | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |         this._options = options ?? {}; | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 04:02:53 +01:00
										 |  |  |         this.addTag = new SubtleButton(Svg.addSmall_ui(), addAElement) | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |             .SetClass("small-button") | 
					
						
							|  |  |  |             .onClick(() => { | 
					
						
							|  |  |  |                 this.IsSelected.setData(true); | 
					
						
							|  |  |  |                 value.data.push(newElement()); | 
					
						
							|  |  |  |                 value.ping(); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         value.map<number>((tags: string[]) => tags.length).addCallback(() => self.createElements(createInput)); | 
					
						
							|  |  |  |         this.createElements(createInput); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this._value.addCallback(tags => self.load(tags)); | 
					
						
							|  |  |  |         this.IsSelected = new UIEventSource<boolean>(false); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private load(tags: T[]) { | 
					
						
							|  |  |  |         if (tags === undefined) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         for (let i = 0; i < tags.length; i++) { | 
					
						
							|  |  |  |             this.inputELements[i].GetValue().setData(tags[i]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     private UpdateIsSelected(){ | 
					
						
							|  |  |  |         this.IsSelected.setData(this.inputELements.map(input => input.IsSelected.data).reduce((a,b) => a && b)) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private createElements(createInput: (() => InputElement<T>)) { | 
					
						
							|  |  |  |         this.inputELements.splice(0, this.inputELements.length); | 
					
						
							|  |  |  |         this.elements = []; | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         for (let i = 0; i < this._value.data.length; i++) { | 
					
						
							|  |  |  |             const input = createInput(); | 
					
						
							|  |  |  |             input.GetValue().addCallback(tag => { | 
					
						
							|  |  |  |                     self._value.data[i] = tag; | 
					
						
							|  |  |  |                     self._value.ping(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |             this.inputELements.push(input); | 
					
						
							|  |  |  |             input.IsSelected.addCallback(() => this.UpdateIsSelected()); | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 04:02:53 +01:00
										 |  |  |             const moveUpBtn = Svg.up_ui() | 
					
						
							| 
									
										
										
										
											2020-11-12 12:18:02 +01:00
										 |  |  |                 .SetClass('small-image').onClick(() => { | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |                     const v = self._value.data[i]; | 
					
						
							|  |  |  |                     self._value.data[i] = self._value.data[i - 1]; | 
					
						
							|  |  |  |                     self._value.data[i - 1] = v; | 
					
						
							|  |  |  |                     self._value.ping(); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 03:17:27 +01:00
										 |  |  |             const moveDownBtn =  | 
					
						
							| 
									
										
										
										
											2020-11-12 12:18:02 +01:00
										 |  |  |                 Svg.down_ui() | 
					
						
							|  |  |  |                     .SetClass('small-image') .onClick(() => { | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |                     const v = self._value.data[i]; | 
					
						
							|  |  |  |                     self._value.data[i] = self._value.data[i + 1]; | 
					
						
							|  |  |  |                     self._value.data[i + 1] = v; | 
					
						
							|  |  |  |                     self._value.ping(); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const controls = []; | 
					
						
							|  |  |  |             if (i > 0 && this._options.allowMovement) { | 
					
						
							|  |  |  |                 controls.push(moveUpBtn); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (i + 1 < this._value.data.length && this._options.allowMovement) { | 
					
						
							|  |  |  |                 controls.push(moveDownBtn); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 03:17:27 +01:00
										 |  |  |             const deleteBtn = | 
					
						
							| 
									
										
										
										
											2020-11-12 12:18:02 +01:00
										 |  |  |                 Svg.delete_icon_ui().SetClass('small-image') | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |                 .onClick(() => { | 
					
						
							|  |  |  |                     self._value.data.splice(i, 1); | 
					
						
							|  |  |  |                     self._value.ping(); | 
					
						
							|  |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2020-09-05 15:27:35 +02:00
										 |  |  |             controls.push(deleteBtn); | 
					
						
							|  |  |  |             this.elements.push(new Combine([input.SetStyle("width: calc(100% - 2em - 5px)"), new Combine(controls).SetStyle("display:flex;flex-direction:column;width:min-content;")]).SetClass("tag-input-row")) | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         this.Update(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InnerRender(): string { | 
					
						
							|  |  |  |         return new Combine([...this.elements, this.addTag]).Render(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     IsValid(t: T[]): boolean { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GetValue(): UIEventSource<T[]> { | 
					
						
							|  |  |  |         return this._value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |