| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | import {InputElement} from "./InputElement"; | 
					
						
							| 
									
										
										
										
											2020-08-17 17:23:15 +02:00
										 |  |  | import {UIEventSource} from "../../Logic/UIEventSource"; | 
					
						
							| 
									
										
										
										
											2020-09-03 00:00:37 +02:00
										 |  |  | import {Utils} from "../../Utils"; | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | export class RadioButton<T> extends InputElement<T> { | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |     IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false); | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     private readonly _selectedElementIndex: UIEventSource<number> | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         = new UIEventSource<number>(null); | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 18:42:13 +02:00
										 |  |  |     private readonly value: UIEventSource<T>; | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     private readonly _elements: InputElement<T>[] | 
					
						
							| 
									
										
										
										
											2020-09-09 18:42:13 +02:00
										 |  |  |     private readonly _selectFirstAsDefault: boolean; | 
					
						
							| 
									
										
										
										
											2021-01-21 05:52:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     constructor(elements: InputElement<T>[], | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                 selectFirstAsDefault = true) { | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  |         super(undefined); | 
					
						
							| 
									
										
										
										
											2020-09-03 00:00:37 +02:00
										 |  |  |         this._elements = Utils.NoNull(elements); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         this._selectFirstAsDefault = selectFirstAsDefault; | 
					
						
							|  |  |  |         const self = this; | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.value = | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |             UIEventSource.flatten(this._selectedElementIndex.map( | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  |                 (selectedIndex) => { | 
					
						
							|  |  |  |                     if (selectedIndex !== undefined && selectedIndex !== null) { | 
					
						
							|  |  |  |                         return elements[selectedIndex].GetValue() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |             ), elements.map(e => e?.GetValue())); | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         this.value.addCallback((t) => { | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |             self?.ShowValue(t); | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         for (let i = 0; i < elements.length; i++) { | 
					
						
							|  |  |  |             // If an element is clicked, the radio button corresponding with it should be selected as well
 | 
					
						
							| 
									
										
										
										
											2020-09-02 11:37:34 +02:00
										 |  |  |             elements[i]?.onClick(() => { | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                 self._selectedElementIndex.setData(i); | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-09-30 22:48:58 +02:00
										 |  |  |             elements[i].IsSelected.addCallback(isSelected => { | 
					
						
							|  |  |  |                 if (isSelected) { | 
					
						
							|  |  |  |                     self._selectedElementIndex.setData(i); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2020-10-17 03:19:14 +02:00
										 |  |  |             elements[i].GetValue().addCallback(() => { | 
					
						
							|  |  |  |                 self._selectedElementIndex.setData(i); | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-27 02:58:11 +01:00
										 |  |  |         this.dumbMode = false; | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     IsValid(t: T): boolean { | 
					
						
							|  |  |  |         for (const inputElement of this._elements) { | 
					
						
							|  |  |  |             if (inputElement.IsValid(t)) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     GetValue(): UIEventSource<T> { | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  |         return this.value; | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |     private IdFor(i) { | 
					
						
							|  |  |  |         return 'radio-' + this.id + '-' + i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 18:24:00 +02:00
										 |  |  |     InnerRender(): string { | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |         let body = ""; | 
					
						
							| 
									
										
										
										
											2020-09-09 22:17:46 +02:00
										 |  |  |         for (let i = 0; i < this._elements.length; i++){ | 
					
						
							|  |  |  |             const el = this._elements[i]; | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |             const htmlElement = | 
					
						
							| 
									
										
										
										
											2021-01-21 06:03:34 +01:00
										 |  |  |                 `<label for="${this.IdFor(i)}" class="question-option-with-border">` + | 
					
						
							|  |  |  |                     `<input type="radio" id="${this.IdFor(i)}" name="radiogroup-${this.id}">` + | 
					
						
							|  |  |  |                     el.Render() + | 
					
						
							|  |  |  |                 `</label>`; | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |             body += htmlElement; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-21 05:53:59 +01:00
										 |  |  |         return `<form id='${this.id}-form'>${body}</form>`; | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 21:03:55 +02:00
										 |  |  |     public ShowValue(t: T): boolean { | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         if (t === undefined) { | 
					
						
							| 
									
										
										
										
											2020-07-20 21:03:55 +02:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!this.IsValid(t)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         // We check that what is selected matches the previous rendering
 | 
					
						
							|  |  |  |         for (let i = 0; i < this._elements.length; i++) { | 
					
						
							|  |  |  |             const e = this._elements[i]; | 
					
						
							|  |  |  |             if (e.IsValid(t)) { | 
					
						
							|  |  |  |                 this._selectedElementIndex.setData(i); | 
					
						
							|  |  |  |                 e.GetValue().setData(t); | 
					
						
							| 
									
										
										
										
											2020-07-20 18:24:00 +02:00
										 |  |  |                 const radio = document.getElementById(this.IdFor(i)); | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                 // @ts-ignore
 | 
					
						
							| 
									
										
										
										
											2020-07-20 18:24:00 +02:00
										 |  |  |                 radio?.checked = true; | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |     InnerUpdate(htmlElement: HTMLElement) { | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         function checkButtons() { | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  |             for (let i = 0; i < self._elements.length; i++) { | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |                 const el = document.getElementById(self.IdFor(i)); | 
					
						
							|  |  |  |                 // @ts-ignore
 | 
					
						
							|  |  |  |                 if (el.checked) { | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                     self._selectedElementIndex.setData(i); | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const el = document.getElementById(this.id); | 
					
						
							|  |  |  |         el.addEventListener("change", | 
					
						
							|  |  |  |             function () { | 
					
						
							|  |  |  |                 checkButtons(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2020-07-20 21:03:55 +02:00
										 |  |  |         if (this._selectedElementIndex.data !== null) { | 
					
						
							|  |  |  |             const el = document.getElementById(this.IdFor(this._selectedElementIndex.data)); | 
					
						
							|  |  |  |             if (el) { | 
					
						
							|  |  |  |                 // @ts-ignore
 | 
					
						
							|  |  |  |                 el.checked = true; | 
					
						
							|  |  |  |                 checkButtons(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (this._selectFirstAsDefault) { | 
					
						
							|  |  |  |             this.ShowValue(this.value.data); | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |             if (this._selectedElementIndex.data === null || this._selectedElementIndex.data === undefined) { | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                 const el = document.getElementById(this.IdFor(0)); | 
					
						
							| 
									
										
										
										
											2020-07-08 16:07:16 +02:00
										 |  |  |                 if (el) { | 
					
						
							|  |  |  |                     // @ts-ignore
 | 
					
						
							|  |  |  |                     el.checked = true; | 
					
						
							|  |  |  |                     checkButtons(); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |