Fix batch pay radio toggle: use persistent JS reference for radio group

The radio group was being removed from DOM then accessed via getElementById
which returned null for detached elements, silently breaking the toggle.
Now uses a persistent JS variable reference that survives DOM removal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Konrad du Plessis 2026-03-24 22:30:11 +02:00
parent 8d13c552aa
commit 9ebaae1b0c

View File

@ -2128,21 +2128,23 @@ document.addEventListener('DOMContentLoaded', function() {
// 'schedule' = split at last paydate (default), 'all' = pay everything unpaid
// --- Helper: Load batch preview for the given mode ---
// Persistent radio group reference (survives DOM removal/re-append)
var _batchRadioGroup = null;
function loadBatchPreview(mode) {
var body = document.getElementById('batchPayModalBody');
var footer = document.getElementById('batchPayModalFooter');
footer.style.display = 'none';
// Keep radio buttons if they exist, clear everything else
var radioGroup = document.getElementById('batchModeRadioGroup');
// Clear all content from modal body
while (body.firstChild) body.removeChild(body.firstChild);
// === Radio button group (always at top) ===
if (!radioGroup) {
radioGroup = document.createElement('div');
radioGroup.id = 'batchModeRadioGroup';
radioGroup.className = 'btn-group w-100 mb-3';
radioGroup.setAttribute('role', 'group');
// === Radio button group (created once, re-appended each time) ===
if (!_batchRadioGroup) {
_batchRadioGroup = document.createElement('div');
_batchRadioGroup.id = 'batchModeRadioGroup';
_batchRadioGroup.className = 'btn-group w-100 mb-3';
_batchRadioGroup.setAttribute('role', 'group');
// "Until Last Paydate" radio
var radioSchedule = document.createElement('input');
@ -2152,7 +2154,7 @@ document.addEventListener('DOMContentLoaded', function() {
radioSchedule.id = 'batchModeSchedule';
radioSchedule.value = 'schedule';
radioSchedule.checked = (mode === 'schedule');
radioGroup.appendChild(radioSchedule);
_batchRadioGroup.appendChild(radioSchedule);
var labelSchedule = document.createElement('label');
labelSchedule.className = 'btn btn-outline-primary';
@ -2161,7 +2163,7 @@ document.addEventListener('DOMContentLoaded', function() {
iconSchedule.className = 'fas fa-calendar-check me-1';
labelSchedule.appendChild(iconSchedule);
labelSchedule.appendChild(document.createTextNode('Until Last Paydate'));
radioGroup.appendChild(labelSchedule);
_batchRadioGroup.appendChild(labelSchedule);
// "Pay All" radio
var radioAll = document.createElement('input');
@ -2171,7 +2173,7 @@ document.addEventListener('DOMContentLoaded', function() {
radioAll.id = 'batchModeAll';
radioAll.value = 'all';
radioAll.checked = (mode === 'all');
radioGroup.appendChild(radioAll);
_batchRadioGroup.appendChild(radioAll);
var labelAll = document.createElement('label');
labelAll.className = 'btn btn-outline-primary';
@ -2180,17 +2182,17 @@ document.addEventListener('DOMContentLoaded', function() {
iconAll.className = 'fas fa-list me-1';
labelAll.appendChild(iconAll);
labelAll.appendChild(document.createTextNode('Pay All'));
radioGroup.appendChild(labelAll);
_batchRadioGroup.appendChild(labelAll);
// Re-fetch preview when radio changes
radioSchedule.addEventListener('change', function() { loadBatchPreview('schedule'); });
radioAll.addEventListener('change', function() { loadBatchPreview('all'); });
} else {
// Update checked state on existing radios
document.getElementById('batchModeSchedule').checked = (mode === 'schedule');
document.getElementById('batchModeAll').checked = (mode === 'all');
// Update checked state using the saved reference (not getElementById — element is detached)
_batchRadioGroup.querySelector('#batchModeSchedule').checked = (mode === 'schedule');
_batchRadioGroup.querySelector('#batchModeAll').checked = (mode === 'all');
}
body.appendChild(radioGroup);
body.appendChild(_batchRadioGroup);
// Show loading spinner below radio buttons
var loadDiv = document.createElement('div');
@ -2344,9 +2346,8 @@ document.addEventListener('DOMContentLoaded', function() {
if (batchPayBtn) {
batchPayBtn.addEventListener('click', function() {
var modal = new bootstrap.Modal(document.getElementById('batchPayModal'));
// Reset radio group so it gets re-created fresh
var oldRadio = document.getElementById('batchModeRadioGroup');
if (oldRadio) oldRadio.remove();
// Reset radio group so it gets re-created fresh each time modal opens
_batchRadioGroup = null;
modal.show();
// Default mode: split at last paydate
loadBatchPreview('schedule');