import { isSelectElement, isCheckboxOrRadioInputElement, show, hide, enable, disable } from '@utils'; import { z } from 'zod'; import { ApplicationController } from './application_controller'; export class ChampDropdownController extends ApplicationController { connect() { this.on('change', (event) => this.onChange(event)); } private onChange(event: Event) { const target = event.target as HTMLInputElement; if (!target.disabled) { if (isSelectElement(target) || isCheckboxOrRadioInputElement(target)) { this.toggleOtherInput(target); this.toggleLinkedSelect(target); } } } private toggleOtherInput(target: HTMLSelectElement | HTMLInputElement) { const parent = target.closest('.editable-champ-drop_down_list'); const inputGroup = parent?.querySelector('.drop_down_other'); if (inputGroup) { const input = inputGroup.querySelector('input'); if (input) { if (target.value == '__other__') { show(inputGroup); input.disabled = false; input.focus(); } else { hide(inputGroup); input.disabled = true; } } } } private toggleLinkedSelect(target: HTMLSelectElement | HTMLInputElement) { const secondaryOptions = target.dataset.secondaryOptions; if (isSelectElement(target) && secondaryOptions) { const parent = target.closest('.editable-champ-linked_drop_down_list'); const secondary = parent?.querySelector( 'select[data-secondary]' ); if (secondary) { const options = parseOptions(secondaryOptions); this.setSecondaryOptions(secondary, options[target.value]); } } } private setSecondaryOptions( secondarySelectElement: HTMLSelectElement, options: string[] ) { const wrapper = secondarySelectElement.closest('.secondary'); const hidden = wrapper?.nextElementSibling as HTMLInputElement | null; secondarySelectElement.innerHTML = ''; if (options.length) { disable(hidden); if (secondarySelectElement.required) { secondarySelectElement.appendChild(makeOption('')); } for (const option of options) { secondarySelectElement.appendChild(makeOption(option)); } secondarySelectElement.selectedIndex = 0; enable(secondarySelectElement); show(wrapper); } else { hide(wrapper); disable(secondarySelectElement); enable(hidden); } } } const SecondaryOptions = z.record(z.string().array()); function parseOptions(options: string) { return SecondaryOptions.parse(JSON.parse(options)); } function makeOption(option: string) { const element = document.createElement('option'); element.textContent = option; element.value = option; return element; }