mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-09-25 09:53:08 +02:00
95 lines
2.9 KiB
JavaScript
95 lines
2.9 KiB
JavaScript
/**
|
|
* admin-contacts-form.js — Dynamic contact group/entry management.
|
|
*
|
|
* Reads `data-apropos-key` and `data-apropos-group-count` from the form element.
|
|
* Expects templates with ids `entry-template-f-{key}` and `group-template-f-{key}`.
|
|
*/
|
|
(() => {
|
|
var form = document.querySelector("form[data-apropos-key]");
|
|
if (!form) return;
|
|
|
|
var key = form.dataset.aproposKey;
|
|
var groupCount = parseInt(form.dataset.aproposGroupCount, 10) || 0;
|
|
var entryTpl = document.getElementById(`entry-template-f-${key}`).innerHTML;
|
|
var groupTpl = document.getElementById(`group-template-f-${key}`).innerHTML;
|
|
|
|
function reindexGroups() {
|
|
var fieldsets = form.querySelectorAll("fieldset.apropos-group");
|
|
groupCount = fieldsets.length;
|
|
fieldsets.forEach((fs, i) => {
|
|
var newIdx = i;
|
|
var legend = fs.querySelector("legend");
|
|
if (legend) legend.textContent = `Contact ${newIdx + 1}`;
|
|
|
|
fs.querySelectorAll("input").forEach((inp) => {
|
|
if (inp.name) {
|
|
inp.name = inp.name.replace(/groups\[\d+\]/, `groups[${newIdx}]`);
|
|
}
|
|
if (inp.id) {
|
|
inp.id = inp.id.replace(
|
|
/(group_f_contacts_|entry_f_contacts_)\d+/,
|
|
`$1${newIdx}`,
|
|
);
|
|
}
|
|
});
|
|
|
|
fs.querySelectorAll("label[for]").forEach((lbl) => {
|
|
lbl.setAttribute(
|
|
"for",
|
|
lbl
|
|
.getAttribute("for")
|
|
.replace(/(group_f_contacts_|entry_f_contacts_)\d+/, `$1${newIdx}`),
|
|
);
|
|
});
|
|
|
|
var addBtn = fs.querySelector(".add-entry-btn-f");
|
|
if (addBtn) addBtn.dataset.group = newIdx;
|
|
});
|
|
}
|
|
|
|
function bindAddEntry(btn) {
|
|
btn.addEventListener("click", function () {
|
|
var gi = parseInt(this.dataset.group, 10);
|
|
var fieldset = this.closest("fieldset");
|
|
var entryCount = fieldset.querySelectorAll(".apropos-entry").length;
|
|
var html = entryTpl
|
|
.replaceAll("{{gi}}", gi)
|
|
.replaceAll("{{ei}}", entryCount);
|
|
this.insertAdjacentHTML("beforebegin", html);
|
|
});
|
|
}
|
|
|
|
function bindDeleteGroup(btn) {
|
|
btn.addEventListener("click", function () {
|
|
var fieldset = this.closest("fieldset");
|
|
if (fieldset) {
|
|
fieldset.remove();
|
|
reindexGroups();
|
|
// Trigger htmx autosave so deletion is persisted
|
|
form.dispatchEvent(new Event("change", { bubbles: true }));
|
|
}
|
|
});
|
|
}
|
|
|
|
// Bind existing buttons
|
|
form.querySelectorAll(".add-entry-btn-f").forEach(bindAddEntry);
|
|
form.querySelectorAll(".delete-group-btn-f").forEach(bindDeleteGroup);
|
|
|
|
form.querySelector(".add-group-btn-f").addEventListener("click", function () {
|
|
groupCount++;
|
|
var html = groupTpl.replaceAll("{{gi}}", groupCount);
|
|
this.insertAdjacentHTML("beforebegin", html);
|
|
|
|
var newGroup = this.previousElementSibling;
|
|
if (newGroup?.classList.contains("apropos-group")) {
|
|
var addBtn = newGroup.querySelector(".add-entry-btn-f");
|
|
if (addBtn) {
|
|
addBtn.dataset.group = groupCount;
|
|
bindAddEntry(addBtn);
|
|
}
|
|
var delBtn = newGroup.querySelector(".delete-group-btn-f");
|
|
if (delBtn) bindDeleteGroup(delBtn);
|
|
}
|
|
});
|
|
})();
|