diff --git a/.last-branch b/.last-branch index e0b81af..db6f598 100644 --- a/.last-branch +++ b/.last-branch @@ -1 +1 @@ -v20260101-12-run-checks-select-all-indeterminate-clear-selection-fix +v20260101-13-run-checks-select-all-indeterminate-state-fix diff --git a/containers/backupchecks/src/templates/main/run_checks.html b/containers/backupchecks/src/templates/main/run_checks.html index b014c3d..2518511 100644 --- a/containers/backupchecks/src/templates/main/run_checks.html +++ b/containers/backupchecks/src/templates/main/run_checks.html @@ -381,57 +381,57 @@ function statusClass(status) { } if (selectAll) { - function clearAllSelection() { + function setAllSelection(checked) { var cbs = table.querySelectorAll('tbody .rc_row_cb'); - cbs.forEach(function (cb) { cb.checked = false; }); - // Ensure header checkbox is reset as well. + cbs.forEach(function (cb) { cb.checked = !!checked; }); + + // Keep header checkbox state in sync and avoid a "stuck" indeterminate UI. selectAll.indeterminate = false; - selectAll.checked = false; + selectAll.checked = !!checked; + updateButtons(); } - // When the header checkbox is indeterminate (partial selection), users expect a click - // to clear the selection, not to select everything. - var selectAllWasIndeterminate = false; - - selectAll.addEventListener('mousedown', function () { - selectAllWasIndeterminate = !!selectAll.indeterminate; - }, true); - - selectAll.addEventListener('click', function (e) { - if (selectAllWasIndeterminate) { + function toggleHeaderSelection(e) { + if (e) { e.preventDefault(); e.stopPropagation(); - clearAllSelection(); - selectAllWasIndeterminate = false; - } - }, true); - - selectAll.addEventListener('keydown', function (e) { - // Space toggles checkboxes. If indeterminate, treat Space as "clear selection". - if ((e.key === ' ' || e.code === 'Space') && selectAll.indeterminate) { - e.preventDefault(); - e.stopPropagation(); - clearAllSelection(); - } - }, true); - - selectAll.addEventListener('change', function () { - // Safety net: if any browser still fires change after an indeterminate click, - // force the expected "clear" behavior. - if (selectAllWasIndeterminate) { - clearAllSelection(); - selectAllWasIndeterminate = false; - return; } var cbs = table.querySelectorAll('tbody .rc_row_cb'); - cbs.forEach(function (cb) { cb.checked = selectAll.checked; }); - updateButtons(); - }); + var total = cbs.length; + if (!total) { + // No rows; always reset header state. + selectAll.indeterminate = false; + selectAll.checked = false; + updateButtons(); + return; + } + + var checked = 0; + cbs.forEach(function (cb) { if (cb.checked) checked++; }); + + // Behavior: + // - none selected => select all + // - all selected => clear all + // - partial selection (indeterminate) => clear selection + var target = (checked === 0); + + setAllSelection(target); + } + + // Fully control header checkbox behavior to prevent indeterminate state from getting stuck. + selectAll.addEventListener('click', toggleHeaderSelection, true); + + selectAll.addEventListener('keydown', function (e) { + // Space/Enter should behave the same as a click. + if (e.key === ' ' || e.code === 'Space' || e.key === 'Enter') { + toggleHeaderSelection(e); + } + }, true); } -// Prevent browser text selection when using Shift with checkbox selection + // Prevent browser text selection when using Shift with checkbox selection table.addEventListener('mousedown', function (e) { var t = e.target; if (!t) return; diff --git a/docs/changelog.md b/docs/changelog.md index 20579d4..d6dc80c 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -192,6 +192,15 @@ - Implemented click interception before the browser toggles the checkbox state to prevent unintended full selection from the indeterminate state. - Added consistent keyboard behavior: pressing Space on the indeterminate header checkbox now also clears the selection. +--- + +## v20260101-13-run-checks-select-all-indeterminate-state-fix + +- Fixed the “Select all” checkbox behavior on the Run Checks page. +- Resolved an issue where the checkbox remained in the indeterminate (`-`) state after clearing the selection. +- Ensured that after clearing all selected rows, the “Select all” checkbox can again be used to select all rows normally. +- Improved synchronization between individual row selection and the global “Select all” checkbox state. + ================================================================================================================================================ ## v0.1.14