A high-performance, feature-rich sortable table library with custom cell renderers, interactive histograms, virtual scrolling, and advanced data manipulation capabilities.
npm install sortable-table
<script type="importmap">
{
"imports": {
"d3": "https://cdn.jsdelivr.net/npm/d3@7/+esm",
"clusterize.js": "https://cdn.jsdelivr.net/npm/clusterize.js@0.19.0/+esm"
}
}
</script>
<script type="module">
import { sorterTable } from './dist/sorter-table.esm.js';
</script>
git clone <repository-url>
cd sorter-table-vis
npm install
npm run build
import { sorterTable } from './dist/sorter-table.esm.js';
// Sample data
const data = [
{ id: 1, name: 'Alice', age: 30, salary: 50000 },
{ id: 2, name: 'Bob', age: 25, salary: 45000 },
{ id: 3, name: 'Charlie', age: 35, salary: 60000 }
];
const columnNames = ['id', 'name', 'age', 'salary'];
// Change callback
function onTableChange(event) {
console.log('Table changed:', event);
}
// Create table instance
const table = new sorterTable(data, columnNames, onTableChange, {
height: '600px',
width: '100%'
});
// Render table
const container = document.getElementById('table-container');
container.appendChild(table.getNode());
const cellRenderers = {
salary: (value, rowData) => {
const div = document.createElement('div');
div.style.backgroundColor = value > 50000 ? '#4caf50' : '#ff9800';
div.style.padding = '6px';
div.style.borderRadius = '4px';
div.style.color = 'white';
div.style.textAlign = 'center';
div.textContent = `$${value.toLocaleString()}`;
return div;
},
age: (value, rowData) => {
const progress = (value / 100) * 100;
const div = document.createElement('div');
div.style.width = '100px';
div.style.height = '20px';
div.style.backgroundColor = '#e0e0e0';
div.style.borderRadius = '10px';
div.style.overflow = 'hidden';
const bar = document.createElement('div');
bar.style.width = `${progress}%`;
bar.style.height = '100%';
bar.style.backgroundColor = '#2196F3';
div.appendChild(bar);
return div;
}
};
const table = new sorterTable(data, columnNames, onTableChange, {
cellRenderers: cellRenderers,
height: '600px'
});
const options = {
// Container dimensions
height: '400px', // Container height (default: '400px')
width: '100%', // Container width (default: '100%')
// Rendering
rowsPerPage: 50, // Rows per page for pagination (default: 50)
useWindowing: true, // Enable virtual scrolling (default: true)
rowHeight: 30, // Row height in pixels (default: 30)
bufferRows: 10, // Extra rows to render for smooth scrolling (default: 10)
// Performance
useWorkers: true, // Use Web Workers for histogram calculations (default: true)
workerPoolSize: 2, // Number of worker threads (default: 2)
samplingThreshold: 50000, // Use sampling for datasets > 50k (default: 50000)
maxSampleSize: 50000, // Maximum sample size (default: 50000)
// Binning
maxOrdinalBins: 12, // Maximum bins for categorical data (default: 12)
continuousBinMethod: 'scott', // Binning method: 'scott', 'fd', 'sturges' (default: 'scott')
dateInterval: 'day', // Date binning interval (default: 'day')
minBinSize: 5, // Minimum bin size (default: 5)
// Custom renderers
cellRenderers: {}, // Object mapping column names to renderer functions
// UI
showDefaultControls: true, // Show default toolbar controls (default: true)
// Callbacks
onNearEnd: null // Callback when scrolling near end
};
See API.md for complete API documentation.
updateData(newData, options) - Update table dataresetTable(useInitialData, options) - Reset table to initial statefilter() - Apply current selection as filterapplyCustomFilter(filterFunction, options) - Apply custom filter functiongroupBy(groupColumns, aggregators) - Group data by columnsungroup() - Remove groupingsetSelectedData(selectedIndices) - Select rows by indexsetSelectedDataByIds(ids, idPropertyName) - Select rows by IDgetSelection() - Get currently selected row indicesclearSelection() - Clear all selectionssetColumnType(columnName, type) - Set column data typegetColumnValues(columnName, options) - Get column valuesshiftCol(columnName, direction) - Reorder columnsgetNode() - Get table DOM nodesetContainerSize(options) - Update container dimensionsrebuildTable() - Rebuild table (after data changes)undo() - Undo last operationconst table = new sorterTable(data, columns, onChange);
document.getElementById('container').appendChild(table.getNode());
const table = new sorterTable(largeData, columns, onChange, {
samplingThreshold: 100000,
maxSampleSize: 50000,
useWorkers: true,
workerPoolSize: 4
});
// Group by 'category' column, aggregate 'sales' with sum
table.groupBy(['category'], {
sales: {
fn: (values) => values.reduce((a, b) => a + b, 0),
label: 'Total Sales'
}
});
table.applyCustomFilter((rowData) => {
return rowData.age > 25 && rowData.salary > 50000;
}, {
customRule: 'Age > 25 and Salary > 50000'
});
See the examples/ directory for more complete examples.
Requires ES6+ support and Web Workers (for histogram calculations).
ISC
Contributions are welcome! Please ensure: