demarches-normaliennes/app/javascript/controllers/select_champ_position_template_controller.ts

80 lines
2.6 KiB
TypeScript

import { ApplicationController } from './application_controller';
export class SelectChampPositionTemplateController extends ApplicationController {
static targets = ['select', 'template'];
static values = {
templateId: String
};
// this element is updated via turbostream as the source of truth for all select
declare readonly templateIdValue: string;
declare readonly selectTargets: HTMLSelectElement[];
selectTargetConnected(selectElement: HTMLSelectElement) {
selectElement.addEventListener('focus', this);
selectElement.addEventListener('change', this);
}
selectTargetDisconnected(selectElement: HTMLSelectElement) {
selectElement.removeEventListener('focus', this);
selectElement.removeEventListener('change', this);
}
handleEvent(event: Event) {
switch (event.type) {
case 'focus':
this.onFocus(event);
break;
case 'change':
this.onChange(event);
break;
}
}
private onFocus(event: Event): void {
const focusedSelect = event.target as HTMLSelectElement;
const focusedSelectStableId = this.getStableIdForSelect(focusedSelect);
const template = this.element.querySelector<HTMLElement>(
`#${this.templateIdValue}`
);
if (template) {
const fragment = template.cloneNode(true) as HTMLSelectElement;
const options = Array.from(fragment.querySelectorAll('option'));
options.map((option) => {
// can't move current element after current element
if (option.value == focusedSelectStableId) {
option.setAttribute('selected', 'selected');
option.setAttribute('disabled', 'disabled');
}
});
options.map((option, index) => {
const previousOption = options[index - 1];
// can't move current element after previous element
if (previousOption && option.value == focusedSelectStableId) {
previousOption.setAttribute('selected', 'selected');
previousOption.setAttribute('disabled', 'disabled');
}
});
focusedSelect.innerHTML = options
.map((option) => option.outerHTML)
.join('');
}
}
private onChange(event: Event): void {
const changedSelectTarget = event.target as HTMLSelectElement;
const stableIdDidChange =
changedSelectTarget.value !=
this.getStableIdForSelect(changedSelectTarget);
if (stableIdDidChange) {
changedSelectTarget.form?.requestSubmit();
}
event.stopImmediatePropagation();
}
private getStableIdForSelect(select: HTMLSelectElement): string | null {
return select.getAttribute('data-selected');
}
}