function registerPricingPanelToggler() { const checkbox = document.querySelector( `input[type="checkbox"][id$="id_free"]` ); const specificPricingPanel = document.querySelector( `div#specific_pricing_panel` ); function onChange() { specificPricingPanel.style.display = checkbox.checked ? "none" : "block"; } if (checkbox && specificPricingPanel) { checkbox.addEventListener("change", () => onChange()); onChange(); } } // Adds a "Duplicate" button to each event occurrence ("Forekomst") row, copying // its date, time and venue. Wagtail's InlinePanel has no native duplicate. function registerOccurrenceCloning() { const FORMSET_PREFIX = "occurrences"; const container = document.getElementById(`id_${FORMSET_PREFIX}-FORMS`); if (!container) return; // not an event page const FIELDS = ["start", "end", "venue", "venue_custom"]; const duplicateIcon = ''; function duplicateRow(sourceChild) { const addButton = document.getElementById(`id_${FORMSET_PREFIX}-ADD`); const totalForms = document.getElementById( `id_${FORMSET_PREFIX}-TOTAL_FORMS` ); if (!addButton || !totalForms) return; // `inline_child_occurrences-0` -> form prefix `occurrences-0`, used by field ids. const sourcePrefix = sourceChild.id.replace(/^inline_child_/, ""); const values = {}; FIELDS.forEach((name) => { const field = document.getElementById(`id_${sourcePrefix}-${name}`); values[name] = field ? field.value : ""; }); // The new form takes the current TOTAL_FORMS index. Click Wagtail's real // "Add" so it appends and initialises the row (e.g. date/time pickers). const newIndex = parseInt(totalForms.value, 10); addButton.click(); const newPrefix = `${FORMSET_PREFIX}-${newIndex}`; FIELDS.forEach((name) => { const field = document.getElementById(`id_${newPrefix}-${name}`); if (!field) return; field.value = values[name]; field.dispatchEvent(new Event("input", { bubbles: true })); field.dispatchEvent(new Event("change", { bubbles: true })); }); } function addDuplicateButton(child) { const controls = child.querySelector("[data-panel-controls]"); if (!controls || controls.querySelector("[data-duplicate-occurrence]")) return; const button = document.createElement("button"); button.type = "button"; button.className = "button button--icon text-replace white"; button.title = "Duplicate"; button.setAttribute("data-duplicate-occurrence", ""); button.innerHTML = duplicateIcon; button.addEventListener("click", () => duplicateRow(child)); // Sit just before the delete button, matching the native control order. const deleteButton = controls.querySelector('[id$="-DELETE-button"]'); controls.insertBefore(button, deleteButton); } function refresh() { container .querySelectorAll("[data-inline-panel-child]") .forEach((child) => addDuplicateButton(child)); } // Cover existing rows plus any added later (via "Add" or "Duplicate"). refresh(); new MutationObserver(() => refresh()).observe(container, { childList: true }); } document.addEventListener("DOMContentLoaded", () => { registerPricingPanelToggler(); registerOccurrenceCloning(); });