| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import { InputElement } from "./InputElement" | 
					
						
							|  |  |  | import { UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  | 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> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private static _nextId = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private readonly value: UIEventSource<T> | 
					
						
							|  |  |  |     private _elements: InputElement<T>[] | 
					
						
							|  |  |  |     private _selectFirstAsDefault: boolean | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |     private _dontStyle: boolean | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         elements: InputElement<T>[], | 
					
						
							|  |  |  |         options?: { | 
					
						
							| 
									
										
										
										
											2022-11-02 14:44:06 +01:00
										 |  |  |             selectFirstAsDefault?: true | boolean | 
					
						
							|  |  |  |             dontStyle?: boolean | 
					
						
							| 
									
										
										
										
											2022-08-05 12:39:02 +02:00
										 |  |  |             value?: UIEventSource<T> | 
					
						
							| 
									
										
										
										
											2021-07-26 17:45:54 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         super() | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |         options = options ?? {} | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._selectFirstAsDefault = options.selectFirstAsDefault ?? true | 
					
						
							|  |  |  |         this._elements = Utils.NoNull(elements) | 
					
						
							| 
									
										
										
										
											2022-10-28 04:33:05 +02:00
										 |  |  |         this.value = options?.value ?? new UIEventSource<T>(undefined) | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |         this._dontStyle = options.dontStyle ?? false | 
					
						
							| 
									
										
										
										
											2021-07-26 17:45:54 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     IsValid(t: T): boolean { | 
					
						
							|  |  |  |         for (const inputElement of this._elements) { | 
					
						
							|  |  |  |             if (inputElement.IsValid(t)) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return true | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return false | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GetValue(): UIEventSource<T> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this.value | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |     protected InnerConstructElement(): HTMLElement { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const elements = this._elements | 
					
						
							|  |  |  |         const selectFirstAsDefault = this._selectFirstAsDefault | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const selectedElementIndex: UIEventSource<number> = new UIEventSource<number>(null) | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const value = UIEventSource.flatten( | 
					
						
							|  |  |  |             selectedElementIndex.map((selectedIndex) => { | 
					
						
							|  |  |  |                 if (selectedIndex !== undefined && selectedIndex !== null) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     return elements[selectedIndex].GetValue() | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             }), | 
					
						
							|  |  |  |             elements.map((e) => e?.GetValue()) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							|  |  |  |         value.syncWith(this.value) | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (selectFirstAsDefault) { | 
					
						
							|  |  |  |             value.addCallbackAndRun((selected) => { | 
					
						
							|  |  |  |                 if (selected === undefined) { | 
					
						
							|  |  |  |                     for (const element of elements) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         const v = element.GetValue().data | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |                         if (v !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             value.setData(v) | 
					
						
							|  |  |  |                             break | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-06-14 02:39:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +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
 | 
					
						
							|  |  |  |             elements[i]?.onClick(() => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 selectedElementIndex.setData(i) | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |             elements[i].GetValue().addCallback(() => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 selectedElementIndex.setData(i) | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-06-14 02:39:23 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-20 13:28:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const groupId = "radiogroup" + RadioButton._nextId | 
					
						
							|  |  |  |         RadioButton._nextId++ | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const form = document.createElement("form") | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const inputs = [] | 
					
						
							|  |  |  |         const wrappers: HTMLElement[] = [] | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |         for (let i1 = 0; i1 < elements.length; i1++) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             let element = elements[i1] | 
					
						
							|  |  |  |             const labelHtml = element.ConstructElement() | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |             if (labelHtml === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const input = document.createElement("input") | 
					
						
							|  |  |  |             input.id = "radio" + groupId + "-" + i1 | 
					
						
							|  |  |  |             input.name = groupId | 
					
						
							|  |  |  |             input.type = "radio" | 
					
						
							|  |  |  |             input.classList.add("cursor-pointer", "p-1", "mr-2") | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (!this._dontStyle) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 input.classList.add("p-1", "ml-2", "pl-2", "pr-0", "m-3", "mr-0") | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             input.onchange = () => { | 
					
						
							|  |  |  |                 if (input.checked) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     selectedElementIndex.setData(i1) | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-06-25 03:39:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             inputs.push(input) | 
					
						
							| 
									
										
										
										
											2021-07-26 17:45:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const label = document.createElement("label") | 
					
						
							|  |  |  |             label.appendChild(labelHtml) | 
					
						
							|  |  |  |             label.htmlFor = input.id | 
					
						
							|  |  |  |             label.classList.add("flex", "w-full", "cursor-pointer", "bg-red") | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (!this._dontStyle) { | 
					
						
							|  |  |  |                 labelHtml.classList.add("p-2") | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const block = document.createElement("div") | 
					
						
							|  |  |  |             block.appendChild(input) | 
					
						
							|  |  |  |             block.appendChild(label) | 
					
						
							|  |  |  |             block.classList.add("flex", "w-full") | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |             if (!this._dontStyle) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 block.classList.add("m-1", "border", "border-gray-400") | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-02-01 19:02:46 +01:00
										 |  |  |             block.style.borderRadius = "1.5rem" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             wrappers.push(block) | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             form.appendChild(block) | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         value.addCallbackAndRun((selected: T) => { | 
					
						
							|  |  |  |             let somethingChecked = false | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |             for (let i = 0; i < inputs.length; i++) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 let input = inputs[i] | 
					
						
							|  |  |  |                 input.checked = !somethingChecked && elements[i].IsValid(selected) | 
					
						
							|  |  |  |                 somethingChecked = somethingChecked || input.checked | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (input.checked) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     wrappers[i].classList.remove("border-gray-400") | 
					
						
							|  |  |  |                     wrappers[i].classList.add("border-attention") | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     wrappers[i].classList.add("border-gray-400") | 
					
						
							|  |  |  |                     wrappers[i].classList.remove("border-attention") | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.SetClass("flex flex-col") | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return form | 
					
						
							| 
									
										
										
										
											2021-07-27 17:00:05 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-26 17:45:54 +02:00
										 |  |  | } |