forked from MapComplete/MapComplete
		
	styling checkbox and selection
This commit is contained in:
		
							parent
							
								
									e9160504a6
								
							
						
					
					
						commit
						263cef5750
					
				
					 5 changed files with 304 additions and 237 deletions
				
			
		|  | @ -74,7 +74,6 @@ export default class FilteringFeatureSource implements FeatureSource { | |||
| 
 | ||||
|           if (FilteringFeatureSource.showLayer(layer, location)) { | ||||
|             const tagsFilter = layer.appliedFilters.data; | ||||
| 
 | ||||
|             if (tagsFilter) { | ||||
|               const properties = f.feature.properties; | ||||
|               if (!tagsFilter.matchesProperties(properties)) { | ||||
|  |  | |||
|  | @ -1,18 +1,12 @@ | |||
| import { Utils } from "./../../Utils"; | ||||
| import { FixedInputElement } from "./../Input/FixedInputElement"; | ||||
| import { RadioButton } from "./../Input/RadioButton"; | ||||
| import { FixedUiElement } from "./../Base/FixedUiElement"; | ||||
| import { LayerConfigJson } from "./../../Customizations/JSON/LayerConfigJson"; | ||||
| import { UIEventSource } from "../../Logic/UIEventSource"; | ||||
| import { VariableUiElement } from "../Base/VariableUIElement"; | ||||
| import State from "../../State"; | ||||
| import Toggle from "../Input/Toggle"; | ||||
| import Combine from "../Base/Combine"; | ||||
| import Translations from "../i18n/Translations"; | ||||
| import LayerConfig from "../../Customizations/JSON/LayerConfig"; | ||||
| import BaseUIElement from "../BaseUIElement"; | ||||
| import { Translation } from "../i18n/Translation"; | ||||
| import ScrollableFullScreen from "../Base/ScrollableFullScreen"; | ||||
| import Svg from "../../Svg"; | ||||
| import FilterConfig from "../../Customizations/JSON/FilterConfig"; | ||||
| import CheckBoxes from "../Input/Checkboxes"; | ||||
|  | @ -20,6 +14,7 @@ import { InputElement } from "../Input/InputElement"; | |||
| import { TagsFilter } from "../../Logic/Tags/TagsFilter"; | ||||
| import InputElementMap from "../Input/InputElementMap"; | ||||
| import { And } from "../../Logic/Tags/And"; | ||||
| import { UIEventSource } from "../../Logic/UIEventSource"; | ||||
| 
 | ||||
| /** | ||||
|  * Shows the filter | ||||
|  | @ -47,7 +42,8 @@ export default class FilterView extends VariableUiElement { | |||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     const style = "display:flex;align-items:center;color:#007759"; | ||||
|     const style = | ||||
|       "display:flex;align-items:center;color:#007759;padding:0.5rem 0;"; | ||||
| 
 | ||||
|     const name: Translation = Translations.WT( | ||||
|       filteredLayer.layerDef.name | ||||
|  | @ -61,23 +57,24 @@ export default class FilterView extends VariableUiElement { | |||
|       .Clone() | ||||
|       .SetStyle("font-size:large;padding-left:1.25rem"); | ||||
| 
 | ||||
|     const layerChecked = new Combine([icon, styledNameChecked]).SetStyle(style); | ||||
|     const layerChecked = new Combine([icon, styledNameChecked]) | ||||
|       .SetStyle(style) | ||||
|       .onClick(() => filteredLayer.isDisplayed.setData(false)); | ||||
| 
 | ||||
|     const layerNotChecked = new Combine([ | ||||
|       iconUnselected, | ||||
|       styledNameUnChecked, | ||||
|     ]).SetStyle(style); | ||||
|     const layerNotChecked = new Combine([iconUnselected, styledNameUnChecked]) | ||||
|       .SetStyle(style) | ||||
|       .onClick(() => filteredLayer.isDisplayed.setData(true)); | ||||
| 
 | ||||
|     let listFilterElements: InputElement<TagsFilter>[] = layer.filters.map( | ||||
|       FilterView.createFilter | ||||
|     ); | ||||
| 
 | ||||
|     function update() { | ||||
|     const update = () => { | ||||
|       let listTagsFilters = Utils.NoNull( | ||||
|         listFilterElements.map((input) => input.GetValue().data) | ||||
|       ); | ||||
|       filteredLayer.appliedTags.setData(new And(listTagsFilters)); | ||||
|     } | ||||
|       filteredLayer.appliedFilters.setData(new And(listTagsFilters)); | ||||
|     }; | ||||
| 
 | ||||
|     listFilterElements.forEach((inputElement) => | ||||
|       inputElement.GetValue().addCallback((_) => update()) | ||||
|  | @ -87,15 +84,20 @@ export default class FilterView extends VariableUiElement { | |||
|       new Combine([layerChecked, ...listFilterElements]), | ||||
|       layerNotChecked, | ||||
|       filteredLayer.isDisplayed | ||||
|     ) | ||||
|       .ToggleOnClick() | ||||
|       .SetStyle("margin:0.3em;"); | ||||
|     ).SetStyle("margin:0.3em;"); | ||||
|   } | ||||
| 
 | ||||
|   static createFilter(filterConfig: FilterConfig): InputElement<TagsFilter> { | ||||
|     if (filterConfig.options.length === 1) { | ||||
|       let option = filterConfig.options[0]; | ||||
|       let checkboxes = new CheckBoxes([option.question.Clone()]); | ||||
|       let checkboxes = new CheckBoxes( | ||||
|         [option.question.Clone()], | ||||
|         new UIEventSource<number[]>([]), | ||||
|         "background-color: #F1F1F1;padding:0.25rem 0.5rem;", | ||||
|         "border:none;padding-left:3rem;color:#007759;display:flex;margin:0;justify-content:center;align-items:center;flex-direction:row;flex-wrap:nowrap;", | ||||
|         "margin:0;padding:0;", | ||||
|         "margin:0;padding:0.25rem 0 0 0.25rem;" | ||||
|       ); | ||||
| 
 | ||||
|       return new InputElementMap( | ||||
|         checkboxes, | ||||
|  | @ -111,7 +113,11 @@ export default class FilterView extends VariableUiElement { | |||
|       options.map( | ||||
|         (option) => | ||||
|           new FixedInputElement(option.question.Clone(), option.osmTags) | ||||
|       ) | ||||
|       ), | ||||
|       true, | ||||
|       "background-color: #F1F1F1;padding:0.25rem 0.5rem;", | ||||
|       "border:none;padding-left:3rem;color:#007759;display:flex;margin:0;justify-content:center;align-items:center;flex-direction:row;flex-wrap:nowrap;", | ||||
|       "margin:0;padding:0;" | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -1,96 +1,110 @@ | |||
| import {InputElement} from "./InputElement"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import {Utils} from "../../Utils"; | ||||
| import { InputElement } from "./InputElement"; | ||||
| import { UIEventSource } from "../../Logic/UIEventSource"; | ||||
| import { Utils } from "../../Utils"; | ||||
| import BaseUIElement from "../BaseUIElement"; | ||||
| 
 | ||||
| /** | ||||
|  * Supports multi-input | ||||
|  */ | ||||
| export default class CheckBoxes extends InputElement<number[]> { | ||||
|     private static _nextId = 0; | ||||
|     IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false); | ||||
|     private readonly value: UIEventSource<number[]> | ||||
|     private readonly _elements: BaseUIElement[]; | ||||
|   private static _nextId = 0; | ||||
|   IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false); | ||||
|   private readonly value: UIEventSource<number[]>; | ||||
|   private readonly _elements: BaseUIElement[]; | ||||
|   private styleWrapperOverride = ""; | ||||
|   private styleInputOverride = ""; | ||||
|   private styleLabelOverride = ""; | ||||
| 
 | ||||
|     constructor(elements: BaseUIElement[], value = new UIEventSource<number[]>([])) { | ||||
|         super(); | ||||
|         this.value = value; | ||||
|         this._elements = Utils.NoNull(elements); | ||||
|         this.SetClass("flex flex-col") | ||||
|   constructor( | ||||
|     elements: BaseUIElement[], | ||||
|     value = new UIEventSource<number[]>([]), | ||||
|     styleFormOverride = "", | ||||
|     styleWrapperOverride = "", | ||||
|     styleInputOverride = "", | ||||
|     styleLabelOverride = "" | ||||
|   ) { | ||||
|     super(); | ||||
|     this.value = value; | ||||
|     this._elements = Utils.NoNull(elements); | ||||
|     this.SetClass("flex flex-col"); | ||||
|     this.SetStyle(styleFormOverride); | ||||
|     this.styleWrapperOverride = styleWrapperOverride; | ||||
|     this.styleInputOverride = styleInputOverride; | ||||
|     this.styleLabelOverride = styleLabelOverride; | ||||
|   } | ||||
| 
 | ||||
|     } | ||||
|   IsValid(ts: number[]): boolean { | ||||
|     return ts !== undefined; | ||||
|   } | ||||
| 
 | ||||
|     IsValid(ts: number[]): boolean { | ||||
|         return ts !== undefined; | ||||
|   GetValue(): UIEventSource<number[]> { | ||||
|     return this.value; | ||||
|   } | ||||
| 
 | ||||
|     } | ||||
|   protected InnerConstructElement(): HTMLElement { | ||||
|     const el = document.createElement("form"); | ||||
| 
 | ||||
|     GetValue(): UIEventSource<number[]> { | ||||
|         return this.value; | ||||
|     } | ||||
|     const value = this.value; | ||||
|     const elements = this._elements; | ||||
| 
 | ||||
|     protected InnerConstructElement(): HTMLElement { | ||||
|         const el = document.createElement("form") | ||||
|     for (let i = 0; i < elements.length; i++) { | ||||
|       let inputI = elements[i]; | ||||
|       const input = document.createElement("input"); | ||||
|       const id = CheckBoxes._nextId; | ||||
|       CheckBoxes._nextId++; | ||||
|       input.id = "checkbox" + id; | ||||
| 
 | ||||
|         const value = this.value; | ||||
|         const elements = this._elements; | ||||
|       input.type = "checkbox"; | ||||
|       input.classList.add("p-1", "cursor-pointer", "m-3", "pl-3", "mr-0"); | ||||
|       input.style.cssText = this.styleInputOverride; | ||||
| 
 | ||||
|         for (let i = 0; i < elements.length; i++) { | ||||
| 
 | ||||
|             let inputI = elements[i]; | ||||
|             const input = document.createElement("input") | ||||
|             const id = CheckBoxes._nextId | ||||
|             CheckBoxes._nextId++; | ||||
|             input.id = "checkbox" + id | ||||
| 
 | ||||
|             input.type = "checkbox" | ||||
|             input.classList.add("p-1","cursor-pointer","m-3","pl-3","mr-0") | ||||
| 
 | ||||
|             const label = document.createElement("label") | ||||
|             label.htmlFor = input.id | ||||
|             label.appendChild(inputI.ConstructElement()) | ||||
|             label.classList.add("block","w-full","p-2","cursor-pointer","bg-red") | ||||
| 
 | ||||
|             const wrapper = document.createElement("span") | ||||
|             wrapper.classList.add("flex","w-full","border", "border-gray-400","m-1") | ||||
|             wrapper.appendChild(input) | ||||
|             wrapper.appendChild(label) | ||||
|             el.appendChild(wrapper) | ||||
|              | ||||
|             value.addCallbackAndRunD(selectedValues => { | ||||
|                 if (selectedValues.indexOf(i) >= 0) { | ||||
|                     input.checked = true; | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
|                 if(input.checked){ | ||||
|                     wrapper.classList.remove("border-gray-400") | ||||
|                     wrapper.classList.add("border-black") | ||||
|                 }else{ | ||||
|                     wrapper.classList.add("border-gray-400") | ||||
|                     wrapper.classList.remove("border-black") | ||||
|                 } | ||||
| 
 | ||||
|             }) | ||||
| 
 | ||||
|             input.onchange = () => { | ||||
|                 // Index = index in the list of already checked items
 | ||||
|                 const index = value.data.indexOf(i); | ||||
|                 if (input.checked && index < 0) { | ||||
|                     value.data.push(i); | ||||
|                     value.ping(); | ||||
|                 } else if (index >= 0) { | ||||
|                     value.data.splice(index, 1); | ||||
|                     value.ping(); | ||||
|                 } | ||||
|             } | ||||
|       const label = document.createElement("label"); | ||||
|       label.htmlFor = input.id; | ||||
|       label.appendChild(inputI.ConstructElement()); | ||||
|       label.classList.add("block", "w-full", "p-2", "cursor-pointer", "bg-red"); | ||||
|       label.style.cssText = this.styleLabelOverride; | ||||
| 
 | ||||
|       const wrapper = document.createElement("span"); | ||||
|       wrapper.classList.add( | ||||
|         "wrapper", | ||||
|         "flex", | ||||
|         "w-full", | ||||
|         "border", | ||||
|         "border-gray-400", | ||||
|         "m-1" | ||||
|       ); | ||||
|       wrapper.style.cssText = this.styleWrapperOverride; | ||||
|       wrapper.appendChild(input); | ||||
|       wrapper.appendChild(label); | ||||
|       el.appendChild(wrapper); | ||||
| 
 | ||||
|       value.addCallbackAndRunD((selectedValues) => { | ||||
|         if (selectedValues.indexOf(i) >= 0) { | ||||
|           input.checked = true; | ||||
|         } | ||||
| 
 | ||||
|         if (input.checked) { | ||||
|           wrapper.classList.remove("border-gray-400"); | ||||
|           wrapper.classList.add("border-black"); | ||||
|         } else { | ||||
|           wrapper.classList.add("border-gray-400"); | ||||
|           wrapper.classList.remove("border-black"); | ||||
|         } | ||||
|       }); | ||||
| 
 | ||||
|         return el; | ||||
|       input.onchange = () => { | ||||
|         // Index = index in the list of already checked items
 | ||||
|         const index = value.data.indexOf(i); | ||||
|         if (input.checked && index < 0) { | ||||
|           value.data.push(i); | ||||
|           value.ping(); | ||||
|         } else if (index >= 0) { | ||||
|           value.data.splice(index, 1); | ||||
|           value.ping(); | ||||
|         } | ||||
|       }; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     return el; | ||||
|   } | ||||
| } | ||||
|  | @ -1,157 +1,179 @@ | |||
| import {InputElement} from "./InputElement"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import {Utils} from "../../Utils"; | ||||
| import { InputElement } from "./InputElement"; | ||||
| import { UIEventSource } from "../../Logic/UIEventSource"; | ||||
| import { Utils } from "../../Utils"; | ||||
| 
 | ||||
| export class RadioButton<T> extends InputElement<T> { | ||||
|     private static _nextId = 0; | ||||
|     IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false); | ||||
|     private readonly value: UIEventSource<T>; | ||||
|     private _elements: InputElement<T>[]; | ||||
|     private _selectFirstAsDefault: boolean; | ||||
|   private static _nextId = 0; | ||||
|   IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false); | ||||
|   private readonly value: UIEventSource<T>; | ||||
|   private _elements: InputElement<T>[]; | ||||
|   private _selectFirstAsDefault: boolean; | ||||
|   private styleFormOverride = ""; | ||||
|   private styleBlockOverride = ""; | ||||
|   private styleInputOverride = ""; | ||||
|   private styleLabelOverride = ""; | ||||
| 
 | ||||
|     constructor(elements: InputElement<T>[], | ||||
|                 selectFirstAsDefault = true) { | ||||
|         super() | ||||
|         this._selectFirstAsDefault = selectFirstAsDefault; | ||||
|         this._elements = Utils.NoNull(elements); | ||||
|         this.value = new UIEventSource<T>(undefined) | ||||
|     } | ||||
|     protected InnerConstructElement(): HTMLElement { | ||||
|         const elements = this._elements; | ||||
|         const selectFirstAsDefault = this._selectFirstAsDefault; | ||||
|   constructor( | ||||
|     elements: InputElement<T>[], | ||||
|     selectFirstAsDefault = true, | ||||
|     styleFormOverride = "", | ||||
|     styleBlockOverride = "", | ||||
|     styleInputOverride = "", | ||||
|     styleLabelOverride = "" | ||||
|   ) { | ||||
|     super(); | ||||
|     this._selectFirstAsDefault = selectFirstAsDefault; | ||||
|     this._elements = Utils.NoNull(elements); | ||||
|     this.value = new UIEventSource<T>(undefined); | ||||
|     this.styleFormOverride = styleFormOverride; | ||||
|     this.styleBlockOverride = styleBlockOverride; | ||||
|     this.styleInputOverride = styleInputOverride; | ||||
|     this.styleLabelOverride = styleLabelOverride; | ||||
|   } | ||||
|   protected InnerConstructElement(): HTMLElement { | ||||
|     const elements = this._elements; | ||||
|     const selectFirstAsDefault = this._selectFirstAsDefault; | ||||
| 
 | ||||
|         const selectedElementIndex: UIEventSource<number> = new UIEventSource<number>(null); | ||||
|         const value = | ||||
|             UIEventSource.flatten(selectedElementIndex.map( | ||||
|                 (selectedIndex) => { | ||||
|                     if (selectedIndex !== undefined && selectedIndex !== null) { | ||||
|                         return elements[selectedIndex].GetValue() | ||||
|                     } | ||||
|                 } | ||||
|             ), elements.map(e => e?.GetValue())); | ||||
|         value.syncWith(this.value) | ||||
|          | ||||
|         if(selectFirstAsDefault){ | ||||
|              | ||||
|         value.addCallbackAndRun(selected =>{ | ||||
|             if(selected === undefined){ | ||||
|                 for (const element of elements) { | ||||
|                     const v = element.GetValue().data; | ||||
|                     if(v !== undefined){ | ||||
|                         value.setData(v) | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|                  | ||||
|             } | ||||
|         }) | ||||
|     const selectedElementIndex: UIEventSource<number> = | ||||
|       new UIEventSource<number>(null); | ||||
| 
 | ||||
|     const value = UIEventSource.flatten( | ||||
|       selectedElementIndex.map((selectedIndex) => { | ||||
|         if (selectedIndex !== undefined && selectedIndex !== null) { | ||||
|           return elements[selectedIndex].GetValue(); | ||||
|         } | ||||
|       }), | ||||
|       elements.map((e) => e?.GetValue()) | ||||
|     ); | ||||
|     value.syncWith(this.value); | ||||
| 
 | ||||
|         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(() => { | ||||
|                 selectedElementIndex.setData(i); | ||||
|             }); | ||||
|             elements[i].IsSelected.addCallback(isSelected => { | ||||
|                 if (isSelected) { | ||||
|                     selectedElementIndex.setData(i); | ||||
|                 } | ||||
|             }) | ||||
|             elements[i].GetValue().addCallback(() => { | ||||
|                 selectedElementIndex.setData(i); | ||||
|             }) | ||||
|     if (selectFirstAsDefault) { | ||||
|       value.addCallbackAndRun((selected) => { | ||||
|         if (selected === undefined) { | ||||
|           for (const element of elements) { | ||||
|             const v = element.GetValue().data; | ||||
|             if (v !== undefined) { | ||||
|               value.setData(v); | ||||
|               break; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         const groupId = "radiogroup" + RadioButton._nextId | ||||
|         RadioButton._nextId++ | ||||
| 
 | ||||
|         const form = document.createElement("form") | ||||
|         const inputs = [] | ||||
|         const wrappers: HTMLElement[] = [] | ||||
|          | ||||
|         for (let i1 = 0; i1 < elements.length; i1++) { | ||||
|             let element = elements[i1]; | ||||
|             const labelHtml = element.ConstructElement(); | ||||
|             if (labelHtml === undefined) { | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             const input = document.createElement("input") | ||||
|             input.id = "radio" + groupId + "-" + i1; | ||||
|             input.name = groupId; | ||||
|             input.type = "radio" | ||||
|                input.classList.add("p-1","cursor-pointer","ml-2","pl-2","pr-0","m-3","mr-0") | ||||
| 
 | ||||
|             input.onchange = () => { | ||||
|                 if(input.checked){ | ||||
|                     selectedElementIndex.setData(i1) | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             | ||||
|             inputs.push(input) | ||||
| 
 | ||||
|             const label = document.createElement("label") | ||||
|             label.appendChild(labelHtml) | ||||
|             label.htmlFor = input.id; | ||||
|             label.classList.add("block","w-full","p-2","cursor-pointer","bg-red") | ||||
| 
 | ||||
| 
 | ||||
|             const block = document.createElement("div") | ||||
|             block.appendChild(input) | ||||
|             block.appendChild(label) | ||||
|             block.classList.add("flex","w-full","border", "rounded-3xl", "border-gray-400","m-1") | ||||
|             wrappers.push(block) | ||||
| 
 | ||||
|             form.appendChild(block) | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         value.addCallbackAndRun( | ||||
|             selected => { | ||||
| 
 | ||||
|                 let somethingChecked = false; | ||||
|                 for (let i = 0; i < inputs.length; i++){ | ||||
|                     let input = inputs[i]; | ||||
|                     input.checked = !somethingChecked && elements[i].IsValid(selected); | ||||
|                     somethingChecked = somethingChecked || input.checked | ||||
| 
 | ||||
|                     if(input.checked){ | ||||
|                         wrappers[i].classList.remove("border-gray-400") | ||||
|                         wrappers[i].classList.add("border-black") | ||||
|                     }else{ | ||||
|                         wrappers[i].classList.add("border-gray-400") | ||||
|                         wrappers[i].classList.remove("border-black") | ||||
|                     } | ||||
| 
 | ||||
|                 } | ||||
|             } | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
|         this.SetClass("flex flex-col") | ||||
|         return form; | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     IsValid(t: T): boolean { | ||||
|         for (const inputElement of this._elements) { | ||||
|             if (inputElement.IsValid(t)) { | ||||
|                 return true; | ||||
|             } | ||||
|     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(() => { | ||||
|         selectedElementIndex.setData(i); | ||||
|       }); | ||||
|       elements[i].IsSelected.addCallback((isSelected) => { | ||||
|         if (isSelected) { | ||||
|           selectedElementIndex.setData(i); | ||||
|         } | ||||
|         return false; | ||||
|       }); | ||||
|       elements[i].GetValue().addCallback(() => { | ||||
|         selectedElementIndex.setData(i); | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     GetValue(): UIEventSource<T> { | ||||
|         return this.value; | ||||
|     const groupId = "radiogroup" + RadioButton._nextId; | ||||
|     RadioButton._nextId++; | ||||
| 
 | ||||
|     const form = document.createElement("form"); | ||||
|     form.style.cssText = this.styleFormOverride; | ||||
| 
 | ||||
|     const inputs = []; | ||||
|     const wrappers: HTMLElement[] = []; | ||||
| 
 | ||||
|     for (let i1 = 0; i1 < elements.length; i1++) { | ||||
|       let element = elements[i1]; | ||||
|       const labelHtml = element.ConstructElement(); | ||||
|       if (labelHtml === undefined) { | ||||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       const input = document.createElement("input"); | ||||
|       input.id = "radio" + groupId + "-" + i1; | ||||
|       input.name = groupId; | ||||
|       input.type = "radio"; | ||||
|       input.classList.add( | ||||
|         "p-1", | ||||
|         "cursor-pointer", | ||||
|         "ml-2", | ||||
|         "pl-2", | ||||
|         "pr-0", | ||||
|         "m-3", | ||||
|         "mr-0" | ||||
|       ); | ||||
|       input.style.cssText = this.styleInputOverride; | ||||
| 
 | ||||
|       input.onchange = () => { | ||||
|         if (input.checked) { | ||||
|           selectedElementIndex.setData(i1); | ||||
|         } | ||||
|       }; | ||||
| 
 | ||||
|       inputs.push(input); | ||||
| 
 | ||||
|       const label = document.createElement("label"); | ||||
|       label.appendChild(labelHtml); | ||||
|       label.htmlFor = input.id; | ||||
|       label.classList.add("block", "w-full", "p-2", "cursor-pointer", "bg-red"); | ||||
|       label.style.cssText = this.styleLabelOverride; | ||||
| 
 | ||||
|       const block = document.createElement("div"); | ||||
|       block.appendChild(input); | ||||
|       block.appendChild(label); | ||||
|       block.classList.add( | ||||
|         "flex", | ||||
|         "w-full", | ||||
|         "border", | ||||
|         "rounded-3xl", | ||||
|         "border-gray-400", | ||||
|         "m-1" | ||||
|       ); | ||||
|       block.style.cssText = this.styleBlockOverride; | ||||
|       wrappers.push(block); | ||||
| 
 | ||||
|       form.appendChild(block); | ||||
|     } | ||||
| 
 | ||||
|     value.addCallbackAndRun((selected) => { | ||||
|       let somethingChecked = false; | ||||
|       for (let i = 0; i < inputs.length; i++) { | ||||
|         let input = inputs[i]; | ||||
|         input.checked = !somethingChecked && elements[i].IsValid(selected); | ||||
|         somethingChecked = somethingChecked || input.checked; | ||||
| 
 | ||||
|         if (input.checked) { | ||||
|           wrappers[i].classList.remove("border-gray-400"); | ||||
|           wrappers[i].classList.add("border-black"); | ||||
|         } else { | ||||
|           wrappers[i].classList.add("border-gray-400"); | ||||
|           wrappers[i].classList.remove("border-black"); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
| 
 | ||||
|     /* | ||||
|     this.SetClass("flex flex-col"); | ||||
| 
 | ||||
|     return form; | ||||
|   } | ||||
| 
 | ||||
|   IsValid(t: T): boolean { | ||||
|     for (const inputElement of this._elements) { | ||||
|       if (inputElement.IsValid(t)) { | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   GetValue(): UIEventSource<T> { | ||||
|     return this.value; | ||||
|   } | ||||
| 
 | ||||
|   /* | ||||
|     public ShowValue(t: T): boolean { | ||||
|         if (t === undefined) { | ||||
|             return false; | ||||
|  | @ -173,6 +195,4 @@ export class RadioButton<T> extends InputElement<T> { | |||
| 
 | ||||
|         } | ||||
|     }*/ | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -421,6 +421,34 @@ | |||
|           "osmTags": "books~.*children.*" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "options": [ | ||||
|         { | ||||
|           "question": "Boeken voor volwassenen aanwezig?", | ||||
|           "osmTags": "books~.*adults.*" | ||||
|         } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       "options": [ | ||||
|         { | ||||
|           "question": "Binnen of buiten", | ||||
|           "osmTags": { | ||||
|             "and": [] | ||||
|           } | ||||
|         }, | ||||
|         { | ||||
|           "question": "Binnen?", | ||||
|           "osmTags": "indoor=yes" | ||||
|         }, | ||||
|         { | ||||
|           "question": "Buiten?", | ||||
|           "osmTags": { | ||||
|             "or": ["indoor=no", "indoor="] | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue