Enhance row selection functionality in SelectionTable to support shift-range selection and improve checkbox handling

This commit is contained in:
Ross
2026-03-25 22:07:56 +00:00
parent 7b52cab180
commit d4f0c05341
+33 -4
View File
@@ -59,6 +59,7 @@ class SelectionTable(tables.Table):
self.caption = self.row_selection_controls
@property
def row_selection_controls(self):
token = (self.attrs or {}).get('data-selection-token', format(id(self), 'x'))
@@ -107,9 +108,9 @@ class SelectionTable(tables.Table):
setCheckboxesDisabled(true); hideSelectionColumn();
table.addEventListener('click', function(e){
if (!selectionEnabled) return;
var tag = (e.target.tagName || '').toLowerCase();
if (['a','button','select','textarea','label'].indexOf(tag) !== -1) return;
// Checkbox clicks should always be handled (support shift-range selection),
// even when row-selection mode is not enabled. Row clicks to toggle a
// checkbox still require selectionEnabled.
if (e.target && e.target.matches && e.target.matches('input[type="checkbox"]')){
var cb = e.target;
if (e.shiftKey && lastChecked && lastChecked !== cb){
@@ -125,9 +126,37 @@ class SelectionTable(tables.Table):
lastChecked = cb;
return;
}
if (!selectionEnabled) return;
var tag = (e.target.tagName || '').toLowerCase();
if (['a','button','select','textarea','label'].indexOf(tag) !== -1) return;
var tr = e.target.closest('tr'); if (!tr || !table.contains(tr)) return;
var cb = tr.querySelector('input[type="checkbox"][name="selection"]') || tr.querySelector('input[type="checkbox"]');
if (cb && !cb.disabled){ cb.checked = !cb.checked; tr.classList.toggle('table-active', cb.checked); updateSelectedCount(); lastChecked = cb; }
if (!cb || cb.disabled) return;
// If the user shift-clicks on a row, perform range selection
if (e.shiftKey && lastChecked && lastChecked !== cb){
var checks = findRowCheckboxes();
var start = checks.indexOf(lastChecked);
var end = checks.indexOf(cb);
if (start > -1 && end > -1){
if (start > end){ var tmp = start; start = end; end = tmp; }
// mirror the checked state of the clicked checkbox
var newState = !cb.checked;
for (var i = start; i <= end; i++){ if (!checks[i].disabled) checks[i].checked = newState; }
updateSelectedCount();
// ensure lastChecked follows the clicked checkbox
lastChecked = cb;
return;
}
}
// Toggle single row checkbox as before
cb.checked = !cb.checked;
tr.classList.toggle('table-active', cb.checked);
updateSelectedCount();
lastChecked = cb;
}, true);
table.addEventListener('change', function(e){ if (e.target && e.target.matches && e.target.matches('input[type="checkbox"]')) updateSelectedCount(); }, true);