Compare commits

...

2 Commits

3 changed files with 39 additions and 41 deletions

View File

@ -1 +1 @@
v20260101-05-run-checks-shift-multiselect v20260101-06-run-checks-shift-multiselect-fix

View File

@ -286,11 +286,6 @@
var btnMarkAllReviewed = document.getElementById('rcm_mark_all_reviewed'); var btnMarkAllReviewed = document.getElementById('rcm_mark_all_reviewed');
// Shift multi-select support for the overview table.
// Works like file explorers: click a checkbox, then Shift+click another checkbox
// to toggle the full range in between.
var lastClickedIndex = null;
function statusClass(status) { function statusClass(status) {
var s = (status || "").toString().toLowerCase(); var s = (status || "").toString().toLowerCase();
@ -348,71 +343,65 @@
return ids.filter(function (x) { return Number.isFinite(x); }); return ids.filter(function (x) { return Number.isFinite(x); });
} }
function updateSelectAllState() {
if (!selectAll) return;
var cbs = table.querySelectorAll('tbody .rc_row_cb');
var total = cbs.length;
var checked = 0;
cbs.forEach(function (cb) { if (cb.checked) checked++; });
if (total === 0) {
selectAll.checked = false;
selectAll.indeterminate = false;
return;
}
selectAll.checked = checked === total;
selectAll.indeterminate = checked > 0 && checked < total;
}
function updateButtons() { function updateButtons() {
var ids = getSelectedJobIds(); var ids = getSelectedJobIds();
if (btnMark) btnMark.disabled = ids.length === 0; if (btnMark) btnMark.disabled = ids.length === 0;
if (btnUnmark) btnUnmark.disabled = ids.length === 0; if (btnUnmark) btnUnmark.disabled = ids.length === 0;
if (statusEl) statusEl.textContent = ids.length ? (ids.length + ' selected') : ''; if (statusEl) statusEl.textContent = ids.length ? (ids.length + ' selected') : '';
updateSelectAllState();
} }
var lastRowCheckbox = null;
if (selectAll) { if (selectAll) {
selectAll.addEventListener('change', function () { selectAll.addEventListener('change', function () {
var cbs = table.querySelectorAll('tbody .rc_row_cb'); var cbs = table.querySelectorAll('tbody .rc_row_cb');
cbs.forEach(function (cb) { cb.checked = selectAll.checked; }); cbs.forEach(function (cb) { cb.checked = selectAll.checked; });
selectAll.indeterminate = false;
updateButtons(); updateButtons();
}); });
} }
// Handle Shift+click range selection on checkboxes. // Shift-click multi select for row checkboxes (continuous range)
table.addEventListener('click', function (e) { table.addEventListener('click', function (e) {
if (!e.target || !e.target.classList || !e.target.classList.contains('rc_row_cb')) return; if (!(e.target && e.target.classList && e.target.classList.contains('rc_row_cb'))) return;
// Prevent row click handlers and stop the browser from doing text-range selection.
e.stopPropagation();
// If shift is held, apply the checkbox state to the whole range.
if (e.shiftKey && lastRowCheckbox && lastRowCheckbox !== e.target) {
var cbs = Array.prototype.slice.call(table.querySelectorAll('tbody .rc_row_cb')); var cbs = Array.prototype.slice.call(table.querySelectorAll('tbody .rc_row_cb'));
var idx = cbs.indexOf(e.target); var start = cbs.indexOf(lastRowCheckbox);
if (idx === -1) return; var end = cbs.indexOf(e.target);
if (e.shiftKey && lastClickedIndex !== null) { if (start !== -1 && end !== -1) {
var start = Math.min(lastClickedIndex, idx); var min = Math.min(start, end);
var end = Math.max(lastClickedIndex, idx); var max = Math.max(start, end);
var newState = e.target.checked; var state = e.target.checked;
for (var i = start; i <= end; i++) {
cbs[i].checked = newState; for (var i = min; i <= max; i++) {
cbs[i].checked = state;
}
} }
} }
lastClickedIndex = idx; lastRowCheckbox = e.target;
// Clear any accidental text selection caused by Shift-click.
try {
var sel = window.getSelection ? window.getSelection() : null;
if (sel && sel.removeAllRanges) sel.removeAllRanges();
} catch (err) {}
updateButtons(); updateButtons();
}); });
// Fallback: any checkbox change should still update the buttons.
table.addEventListener('change', function (e) { table.addEventListener('change', function (e) {
if (e.target && e.target.classList && e.target.classList.contains('rc_row_cb')) { if (e.target && e.target.classList && e.target.classList.contains('rc_row_cb')) {
updateButtons(); updateButtons();
} }
}); });
// Initialize select-all state on page load.
updateButtons();
function postJson(url, body) { function postJson(url, body) {
return fetch(url, { return fetch(url, {
method: 'POST', method: 'POST',

View File

@ -133,6 +133,15 @@
- Users can now select a continuous range of checkboxes by holding Shift and clicking another row. - Users can now select a continuous range of checkboxes by holding Shift and clicking another row.
- Improves efficiency when reviewing or updating multiple checks at once. - Improves efficiency when reviewing or updating multiple checks at once.
---
## v20260101-06-run-checks-shift-multiselect-fix
- Fixed Shift-click behavior on the Run Checks page to properly select a range of rows via checkboxes.
- Prevented default browser text selection when using Shift during checkbox selection.
- Implemented tracking of the last selected checkbox to enable continuous range selection.
- Ensured multiselect only applies to checkbox interactions and not table row text.
================================================================================================================================================ ================================================================================================================================================
## v0.1.14 ## v0.1.14