I can select rows and columns
This commit is contained in:
@@ -1477,8 +1477,87 @@ function initDataGrid(gridId) {
|
||||
updateDatagridSelection(gridId)
|
||||
}
|
||||
|
||||
function initDataGridMouseOver(gridId) {
|
||||
|
||||
/**
|
||||
* Initialize DataGrid hover effects using event delegation.
|
||||
*
|
||||
* Optimizations:
|
||||
* - Event delegation: 1 listener instead of N×2 (where N = number of cells)
|
||||
* - Row mode: O(1) via class toggle on parent row
|
||||
* - Column mode: RAF batching + cached cells for efficient class removal
|
||||
* - Works with HTMX swaps: listener on stable parent, querySelectorAll finds new cells
|
||||
* - No mouseout: hover selection stays visible when leaving the table
|
||||
*
|
||||
* @param {string} gridId - The DataGrid instance ID
|
||||
*/
|
||||
function initDataGridMouseOver(gridId) {
|
||||
const table = document.getElementById(`t_${gridId}`);
|
||||
if (!table) {
|
||||
console.error(`Table with id "t_${gridId}" not found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const wrapper = document.getElementById(`tw_${gridId}`);
|
||||
const selectionModeDiv = document.getElementById(`tsm_${gridId}`);
|
||||
|
||||
// Track hover state
|
||||
let currentHoverRow = null;
|
||||
let currentHoverColId = null;
|
||||
let currentHoverColCells = null;
|
||||
|
||||
table.addEventListener('mouseover', (e) => {
|
||||
// Skip hover during scrolling
|
||||
if (wrapper?.hasAttribute('mf-no-hover')) return;
|
||||
|
||||
const cell = e.target.closest('.dt2-cell');
|
||||
if (!cell) return;
|
||||
|
||||
const selectionMode = selectionModeDiv?.getAttribute('selection-mode');
|
||||
|
||||
if (selectionMode === 'row') {
|
||||
const rowElement = cell.parentElement;
|
||||
if (rowElement !== currentHoverRow) {
|
||||
if (currentHoverRow) {
|
||||
currentHoverRow.classList.remove('dt2-hover-row');
|
||||
}
|
||||
rowElement.classList.add('dt2-hover-row');
|
||||
currentHoverRow = rowElement;
|
||||
}
|
||||
} else if (selectionMode === 'column') {
|
||||
const colId = cell.dataset.col;
|
||||
|
||||
// Skip if same column
|
||||
if (colId === currentHoverColId) return;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
// Remove old column highlight
|
||||
if (currentHoverColCells) {
|
||||
currentHoverColCells.forEach(c => c.classList.remove('dt2-hover-column'));
|
||||
}
|
||||
|
||||
// Query and add new column highlight
|
||||
currentHoverColCells = table.querySelectorAll(`.dt2-cell[data-col="${colId}"]`);
|
||||
currentHoverColCells.forEach(c => c.classList.add('dt2-hover-column'));
|
||||
|
||||
currentHoverColId = colId;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Clean up when leaving the table entirely
|
||||
table.addEventListener('mouseout', (e) => {
|
||||
if (!table.contains(e.relatedTarget)) {
|
||||
if (currentHoverRow) {
|
||||
currentHoverRow.classList.remove('dt2-hover-row');
|
||||
currentHoverRow = null;
|
||||
}
|
||||
if (currentHoverColCells) {
|
||||
currentHoverColCells.forEach(c => c.classList.remove('dt2-hover-column'));
|
||||
currentHoverColCells = null;
|
||||
currentHoverColId = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1638,6 +1717,7 @@ function initDataGridScrollbars(gridId) {
|
||||
dragStartY = e.clientY;
|
||||
dragStartScrollTop = cachedBodyScrollTop;
|
||||
wrapper.setAttribute("mf-no-tooltip", "");
|
||||
wrapper.setAttribute("mf-no-hover", "");
|
||||
}, {signal});
|
||||
|
||||
// Horizontal scrollbar mousedown
|
||||
@@ -1646,6 +1726,7 @@ function initDataGridScrollbars(gridId) {
|
||||
dragStartX = e.clientX;
|
||||
dragStartScrollLeft = cachedTableScrollLeft;
|
||||
wrapper.setAttribute("mf-no-tooltip", "");
|
||||
wrapper.setAttribute("mf-no-hover", "");
|
||||
}, {signal});
|
||||
|
||||
// Consolidated mousemove listener
|
||||
@@ -1684,9 +1765,11 @@ function initDataGridScrollbars(gridId) {
|
||||
if (isDraggingVertical) {
|
||||
isDraggingVertical = false;
|
||||
wrapper.removeAttribute("mf-no-tooltip");
|
||||
wrapper.removeAttribute("mf-no-hover");
|
||||
} else if (isDraggingHorizontal) {
|
||||
isDraggingHorizontal = false;
|
||||
wrapper.removeAttribute("mf-no-tooltip");
|
||||
wrapper.removeAttribute("mf-no-hover");
|
||||
}
|
||||
}, {signal});
|
||||
|
||||
@@ -1694,8 +1777,20 @@ function initDataGridScrollbars(gridId) {
|
||||
let rafScheduledWheel = false;
|
||||
let pendingWheelDeltaX = 0;
|
||||
let pendingWheelDeltaY = 0;
|
||||
let wheelEndTimeout = null;
|
||||
|
||||
const handleWheelScrolling = (event) => {
|
||||
// Disable hover and tooltip during wheel scroll
|
||||
wrapper.setAttribute("mf-no-hover", "");
|
||||
wrapper.setAttribute("mf-no-tooltip", "");
|
||||
|
||||
// Clear previous timeout and re-enable after 150ms of no wheel events
|
||||
if (wheelEndTimeout) clearTimeout(wheelEndTimeout);
|
||||
wheelEndTimeout = setTimeout(() => {
|
||||
wrapper.removeAttribute("mf-no-hover");
|
||||
wrapper.removeAttribute("mf-no-tooltip");
|
||||
}, 150);
|
||||
|
||||
// Accumulate wheel deltas
|
||||
pendingWheelDeltaX += event.deltaX;
|
||||
pendingWheelDeltaY += event.deltaY;
|
||||
|
||||
@@ -179,6 +179,7 @@ class DataGrid(MultipleInstance):
|
||||
df = self._df.copy()
|
||||
df = self._apply_sort(df) # need to keep the real type to sort
|
||||
df = self._apply_filter(df)
|
||||
self._state.ns_total_rows = len(df)
|
||||
|
||||
return df
|
||||
|
||||
@@ -533,7 +534,8 @@ class DataGrid(MultipleInstance):
|
||||
return Div(
|
||||
*[Div(selection_type=s_type, element_id=f"{elt_id}") for s_type, elt_id in selected],
|
||||
id=f"tsm_{self._id}",
|
||||
selection_mode=f"{self._state.selection.selection_mode}",
|
||||
#selection_mode=f"{self._state.selection.selection_mode}",
|
||||
selection_mode=f"column",
|
||||
**extra_attr,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user