Compare commits
2 Commits
7c0c7d8c3e
...
8e6fb4b66d
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e6fb4b66d | |||
| 49629343d5 |
@ -1 +1 @@
|
|||||||
v20260101-06-run-checks-shift-multiselect-fix
|
v20260101-07-run-checks-shift-multiselect-delegation-fix
|
||||||
|
|||||||
@ -286,6 +286,9 @@
|
|||||||
|
|
||||||
var btnMarkAllReviewed = document.getElementById('rcm_mark_all_reviewed');
|
var btnMarkAllReviewed = document.getElementById('rcm_mark_all_reviewed');
|
||||||
|
|
||||||
|
// Shift-click range selection for checkbox rows
|
||||||
|
var lastCheckedCb = null;
|
||||||
|
|
||||||
function statusClass(status) {
|
function statusClass(status) {
|
||||||
var s = (status || "").toString().toLowerCase();
|
var s = (status || "").toString().toLowerCase();
|
||||||
|
|
||||||
@ -348,9 +351,18 @@
|
|||||||
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') : '';
|
||||||
|
refreshSelectAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastRowCheckbox = null;
|
function refreshSelectAll() {
|
||||||
|
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++; });
|
||||||
|
selectAll.indeterminate = checked > 0 && checked < total;
|
||||||
|
selectAll.checked = total > 0 && checked === total;
|
||||||
|
}
|
||||||
|
|
||||||
if (selectAll) {
|
if (selectAll) {
|
||||||
selectAll.addEventListener('change', function () {
|
selectAll.addEventListener('change', function () {
|
||||||
@ -360,47 +372,67 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shift-click multi select for row checkboxes (continuous range)
|
// Prevent browser text selection when using Shift with checkbox selection
|
||||||
table.addEventListener('click', function (e) {
|
table.addEventListener('mousedown', function (e) {
|
||||||
if (!(e.target && e.target.classList && e.target.classList.contains('rc_row_cb'))) return;
|
var t = e.target;
|
||||||
|
if (!t) return;
|
||||||
|
if (t.classList && t.classList.contains('rc_row_cb') && e.shiftKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (window.getSelection) {
|
||||||
|
try { window.getSelection().removeAllRanges(); } catch (err) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
// Prevent row click handlers and stop the browser from doing text-range selection.
|
// Handle Shift-click range selection on the checkbox inputs (delegated)
|
||||||
|
table.addEventListener('click', function (e) {
|
||||||
|
var t = e.target;
|
||||||
|
if (!t || !(t.classList && t.classList.contains('rc_row_cb'))) return;
|
||||||
|
|
||||||
|
// Custom handling so we can reliably read shiftKey and control the toggle + range
|
||||||
|
if (e.shiftKey && lastCheckedCb && lastCheckedCb !== t) {
|
||||||
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// If shift is held, apply the checkbox state to the whole range.
|
// The default action would toggle the checkbox; do it manually
|
||||||
if (e.shiftKey && lastRowCheckbox && lastRowCheckbox !== e.target) {
|
var targetChecked = !t.checked;
|
||||||
|
t.checked = targetChecked;
|
||||||
|
|
||||||
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 start = cbs.indexOf(lastRowCheckbox);
|
var start = cbs.indexOf(lastCheckedCb);
|
||||||
var end = cbs.indexOf(e.target);
|
var end = cbs.indexOf(t);
|
||||||
|
|
||||||
if (start !== -1 && end !== -1) {
|
if (start !== -1 && end !== -1) {
|
||||||
var min = Math.min(start, end);
|
var lo = Math.min(start, end);
|
||||||
var max = Math.max(start, end);
|
var hi = Math.max(start, end);
|
||||||
var state = e.target.checked;
|
for (var i = lo; i <= hi; i++) {
|
||||||
|
cbs[i].checked = targetChecked;
|
||||||
for (var i = min; i <= max; i++) {
|
|
||||||
cbs[i].checked = state;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRowCheckbox = e.target;
|
if (window.getSelection) {
|
||||||
|
try { window.getSelection().removeAllRanges(); } catch (err) {}
|
||||||
// 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();
|
||||||
});
|
lastCheckedCb = t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Fallback: any checkbox change should still update the buttons.
|
// Normal click: let default toggle happen, but remember the last checkbox
|
||||||
table.addEventListener('change', function (e) {
|
lastCheckedCb = t;
|
||||||
|
|
||||||
|
// Defer update until after the checkbox state changes
|
||||||
|
setTimeout(updateButtons, 0);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// Fallback for keyboard toggles (space) and other state changes
|
||||||
|
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')) {
|
||||||
|
lastCheckedCb = e.target;
|
||||||
updateButtons();
|
updateButtons();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function postJson(url, body) {
|
function postJson(url, body) {
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
|
|||||||
@ -142,6 +142,15 @@
|
|||||||
- Implemented tracking of the last selected checkbox to enable continuous range 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.
|
- Ensured multiselect only applies to checkbox interactions and not table row text.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## v20260101-07-run-checks-shift-multiselect-delegation-fix
|
||||||
|
|
||||||
|
- Reworked Shift-click multiselect on the Run Checks page using event delegation.
|
||||||
|
- Ensured checkbox range selection works correctly with dynamically rendered table rows.
|
||||||
|
- Disabled default browser text selection when using Shift during checkbox interaction.
|
||||||
|
- Applied Gmail-style range selection logic for consistent multi-row selection behavior.
|
||||||
|
|
||||||
================================================================================================================================================
|
================================================================================================================================================
|
||||||
## v0.1.14
|
## v0.1.14
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user