|
|
|
|
@ -351,8 +351,19 @@ function statusClass(status) {
|
|
|
|
|
return ids.filter(function (x) { return Number.isFinite(x); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function refreshRowHighlights() {
|
|
|
|
|
var cbs = table.querySelectorAll('tbody .rc_row_cb');
|
|
|
|
|
cbs.forEach(function (cb) {
|
|
|
|
|
var tr = cb.closest ? cb.closest('tr') : null;
|
|
|
|
|
if (!tr) return;
|
|
|
|
|
if (cb.checked) tr.classList.add('table-active');
|
|
|
|
|
else tr.classList.remove('table-active');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateButtons() {
|
|
|
|
|
var ids = getSelectedJobIds();
|
|
|
|
|
refreshRowHighlights();
|
|
|
|
|
if (btnMark) btnMark.disabled = ids.length === 0;
|
|
|
|
|
if (btnUnmark) btnUnmark.disabled = ids.length === 0;
|
|
|
|
|
if (statusEl) statusEl.textContent = ids.length ? (ids.length + ' selected') : '';
|
|
|
|
|
@ -382,10 +393,11 @@ table.addEventListener('mousedown', function (e) {
|
|
|
|
|
var t = e.target;
|
|
|
|
|
if (!t) return;
|
|
|
|
|
|
|
|
|
|
if (t.classList && t.classList.contains('rc_row_cb')) {
|
|
|
|
|
var cb = (t.classList && t.classList.contains('rc_row_cb')) ? t : (t.closest ? t.closest('.rc_row_cb') : null);
|
|
|
|
|
if (cb) {
|
|
|
|
|
// Remember state before click so Shift-click logic can reliably compute the intended target state
|
|
|
|
|
lastMouseDownCb = t;
|
|
|
|
|
lastMouseDownChecked = t.checked;
|
|
|
|
|
lastMouseDownCb = cb;
|
|
|
|
|
lastMouseDownChecked = cb.checked;
|
|
|
|
|
|
|
|
|
|
if (e.shiftKey) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
@ -399,7 +411,10 @@ table.addEventListener('mousedown', function (e) {
|
|
|
|
|
// 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;
|
|
|
|
|
if (!t) return;
|
|
|
|
|
var cb = (t.classList && t.classList.contains('rc_row_cb')) ? t : (t.closest ? t.closest('.rc_row_cb') : null);
|
|
|
|
|
if (!cb) return;
|
|
|
|
|
t = cb;
|
|
|
|
|
|
|
|
|
|
// Custom handling so we can reliably read shiftKey and control the toggle + range
|
|
|
|
|
if (e.shiftKey && lastCheckedCb && lastCheckedCb !== t) {
|
|
|
|
|
@ -416,15 +431,19 @@ table.addEventListener('click', function (e) {
|
|
|
|
|
lastMouseDownCb = null;
|
|
|
|
|
lastMouseDownChecked = null;
|
|
|
|
|
|
|
|
|
|
var cbs = Array.prototype.slice.call(table.querySelectorAll('tbody .rc_row_cb'));
|
|
|
|
|
var start = cbs.indexOf(lastCheckedCb);
|
|
|
|
|
var end = cbs.indexOf(t);
|
|
|
|
|
var rows = Array.prototype.slice.call(table.querySelectorAll('tbody tr'));
|
|
|
|
|
var startRow = lastCheckedCb.closest ? lastCheckedCb.closest('tr') : null;
|
|
|
|
|
var endRow = t.closest ? t.closest('tr') : null;
|
|
|
|
|
|
|
|
|
|
var start = startRow ? rows.indexOf(startRow) : -1;
|
|
|
|
|
var end = endRow ? rows.indexOf(endRow) : -1;
|
|
|
|
|
|
|
|
|
|
if (start !== -1 && end !== -1) {
|
|
|
|
|
var lo = Math.min(start, end);
|
|
|
|
|
var hi = Math.max(start, end);
|
|
|
|
|
for (var i = lo; i <= hi; i++) {
|
|
|
|
|
cbs[i].checked = targetChecked;
|
|
|
|
|
var cb = rows[i].querySelector('.rc_row_cb');
|
|
|
|
|
if (cb) cb.checked = targetChecked;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -451,10 +470,12 @@ table.addEventListener('click', function (e) {
|
|
|
|
|
|
|
|
|
|
// 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')) {
|
|
|
|
|
lastCheckedCb = e.target;
|
|
|
|
|
updateButtons();
|
|
|
|
|
}
|
|
|
|
|
var t = e.target;
|
|
|
|
|
if (!t) return;
|
|
|
|
|
var cb = (t.classList && t.classList.contains('rc_row_cb')) ? t : (t.closest ? t.closest('.rc_row_cb') : null);
|
|
|
|
|
if (!cb) return;
|
|
|
|
|
lastCheckedCb = cb;
|
|
|
|
|
updateButtons();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function postJson(url, body) {
|
|
|
|
|
|