mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-27 13:47:58 +01:00
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import { assertNotNull } from './utils/assert';
|
|
import { $, $$, disableEl, enableEl, removeEl } from './utils/dom';
|
|
import { delegate, leftClick } from './utils/events';
|
|
|
|
export interface InputDuplicatorOptions {
|
|
addButtonSelector: string;
|
|
fieldSelector: string;
|
|
maxInputCountSelector: string;
|
|
removeButtonSelector: string;
|
|
}
|
|
|
|
export function inputDuplicatorCreator({
|
|
addButtonSelector,
|
|
fieldSelector,
|
|
maxInputCountSelector,
|
|
removeButtonSelector,
|
|
}: InputDuplicatorOptions) {
|
|
const addButton = $<HTMLButtonElement>(addButtonSelector);
|
|
if (!addButton) {
|
|
return;
|
|
}
|
|
|
|
const form = assertNotNull(addButton.closest('form'));
|
|
const fieldRemover = (event: MouseEvent, target: HTMLElement) => {
|
|
event.preventDefault();
|
|
|
|
// Prevent removing the final field element to not "brick" the form
|
|
const existingFields = $$(fieldSelector, form);
|
|
if (existingFields.length <= 1) {
|
|
return;
|
|
}
|
|
|
|
removeEl(assertNotNull(target.closest<HTMLElement>(fieldSelector)));
|
|
enableEl(addButton);
|
|
};
|
|
|
|
delegate(form, 'click', {
|
|
[removeButtonSelector]: leftClick(fieldRemover),
|
|
});
|
|
|
|
const maxOptionCountElement = assertNotNull($(maxInputCountSelector, form));
|
|
const maxOptionCount = parseInt(maxOptionCountElement.innerHTML, 10);
|
|
|
|
addButton.addEventListener('click', e => {
|
|
e.preventDefault();
|
|
|
|
const existingFields = $$<HTMLElement>(fieldSelector, form);
|
|
let existingFieldsLength = existingFields.length;
|
|
|
|
if (existingFieldsLength < maxOptionCount) {
|
|
// The last element matched by the `fieldSelector` will be the last field, make a copy
|
|
const prevField = existingFields[existingFieldsLength - 1];
|
|
const prevFieldCopy = prevField.cloneNode(true) as HTMLElement;
|
|
|
|
$$<HTMLInputElement>('input', prevFieldCopy).forEach(prevFieldCopyInput => {
|
|
// Reset new input's value
|
|
prevFieldCopyInput.value = '';
|
|
prevFieldCopyInput.removeAttribute('value');
|
|
|
|
// Increment sequential attributes of the input
|
|
prevFieldCopyInput.setAttribute('name', prevFieldCopyInput.name.replace(/\d+/g, `${existingFieldsLength}`));
|
|
prevFieldCopyInput.setAttribute('id', prevFieldCopyInput.id.replace(/\d+/g, `${existingFieldsLength}`));
|
|
});
|
|
|
|
prevField.insertAdjacentElement('afterend', prevFieldCopy);
|
|
|
|
existingFieldsLength++;
|
|
}
|
|
|
|
// Remove the button if we reached the max number of options
|
|
if (existingFieldsLength >= maxOptionCount) {
|
|
disableEl(addButton);
|
|
}
|
|
});
|
|
}
|