Problem: Row selection was not functioning in virtual scrolling mode even when enabled.
Root Cause: Virtual scrolling dynamically renders rows, but the selection manager's event listeners were only attached to the initial DOM elements.
Solution:
VirtualScrollManager.setupEventDelegation()updateSelectionStates() method to maintain visual selection stateCode Changes:
// Event delegation for dynamically rendered rows
setupEventDelegation() {
this.scrollContainer.addEventListener('click', (event) => {
const row = event.target.closest('.tablix-row');
if (!row) return;
const rowIndex = parseInt(row.getAttribute('data-virtual-index'));
const rowData = this.data[rowIndex];
if (rowData) {
this.table.eventManager.trigger('rowClick', {
rowData, rowIndex, originalEvent: event, element: row
});
}
});
}
Problem: When dragging the scrollbar rapidly, rows would sometimes not render until manual scroll wheel movement.
Root Cause: The throttled scroll handler (16ms delay) was too slow for rapid scrollbar dragging, causing missed scroll events.
Solution:
handleScrollImmediate()Code Changes:
// Immediate scroll handling for fast scrolling
handleScrollImmediate() {
const now = performance.now();
const scrollTop = this.scrollContainer.scrollTop;
// Calculate scroll velocity
if (this.lastScrollTime && this.lastScrollTop !== undefined) {
const timeDelta = now - this.lastScrollTime;
const scrollDelta = Math.abs(scrollTop - this.lastScrollTop);
this.scrollVelocity = timeDelta > 0 ? scrollDelta / timeDelta : 0;
}
// For very fast scrolling, schedule immediate update
if (this.scrollVelocity > 2) {
this.scheduleUpdate();
}
}
Problem: Images would sometimes not load or appear broken during rapid scrolling.
Root Cause: Browser image loading was being interrupted by frequent DOM updates during virtual scrolling.
Solution:
handleImageLoading() method with proper image lifecycle managementCode Changes:
// Optimized image loading
handleImageLoading() {
const images = this.tableBody.querySelectorAll('.tablix-row img');
images.forEach(img => {
if (img.complete || img.classList.contains('loading')) return;
img.classList.add('loading');
img.style.opacity = '0.5';
img.style.transition = 'opacity 0.2s ease';
const handleLoad = () => {
img.classList.remove('loading');
img.style.opacity = '1';
};
img.addEventListener('load', handleLoad);
img.addEventListener('error', handleLoad);
});
}
Run the bug fix tests:
virtual-scroll-bugfix-test.html - Focused testing for specific fixesvirtual-scroll-demo.html - Full demo with all featuresvirtual-scroll-test-suite.html - Comprehensive test suiteSelection Test:
Scrollbar Dragging Test:
Image Loading Test:
Tested and working in:
All fixes maintain backward compatibility with existing TablixJS features.