TablixJS is a modern, lightweight, and dependency-free JavaScript library for building powerful, responsive data tables with comprehensive features. Built with ES6 modules and designed for performance, TablixJS provides advanced pagination, selection, sorting, filtering, search, and data management capabilities with both client-side and server-side support.
- Zero Dependencies - Pure JavaScript with no external libraries required, optional jQuery/React integrations available
- Modular Architecture - Clean separation of concerns with dedicated managers
- Performance Focused - Optimized for large datasets with virtual scrolling support
- Framework Agnostic - Works with vanilla JS, React, jQuery, and other frameworks (all optional)
- TypeScript Ready - ES6 modules with full IDE support
- Highly Customizable - Extensive theming system and plugin architecture
- Accessible - ARIA labels, keyboard navigation, and screen reader support
- Client & Server Modes - Efficient pagination for both local and remote data sources
- Automatic Controls - Auto-generated pagination controls with zero configuration
- Smart Page Navigation - Intelligent page number display with ellipsis for large datasets
- Page Size Management - Dynamic page size selection with customizable options
- Performance Optimized - Efficient data slicing and memory management
- Event Hooks - Complete pagination event system for custom integrations
- Global Search - Real-time search across all columns with customizable debounce
- Advanced Column Filtering - Value-based and condition-based filtering per column
- Filter UI Components - Rich dropdown interfaces with multi-select capabilities
- Server-side Support - Async filtering with custom filter functions
- Filter Persistence - Maintain filters across pagination and data updates
- Visual Indicators - Clear filter status with badges and tooltips
- Multi-column Sorting - Sort by multiple columns with priority indicators
- Data Type Aware - Intelligent sorting for strings, numbers, dates, and custom types
- Client & Server Modes - Local sorting or async server-side sorting
- Custom Sort Functions - Define custom sorting logic per column
- Visual Feedback - Clear sort direction indicators and hover effects
- Stable Sorting - Consistent sort results across operations
- Single & Multi-Row Selection - Choose between single or multiple row selection modes
- Advanced Interaction - Ctrl+click for toggle, Shift+click for range selection
- Drag Selection - Click and drag to select multiple consecutive rows (multi mode)
- Stable Selection - Selection preserved across pagination, filtering, and sorting
- Visual Feedback - Real-time hover effects and drag overlays during selection
- Event System -
beforeSelectandafterSelectevents for custom validation - Programmatic API - Complete selection management through code
- Theme Integration - Consistent selection styling across all themes
- Multiple Loading Methods - Direct arrays, URL endpoints, or custom async functions
- Loading States - Built-in loading indicators and error handling
- Data Transformation - Transform server responses to match table format
- Authentication Support - Custom headers and request configuration
- Error Recovery - Graceful error handling with user feedback
- Event Hooks -
beforeLoad,afterLoad, andloadErrorevents
- CSS Custom Properties - Extensive theming with CSS variables
- Built-in Themes - Light and dark themes included
- Responsive Design - Mobile-friendly controls and layouts
- Component Styling - Modular CSS for easy customization
- Framework Integration - Works seamlessly with existing CSS frameworks
- Built-in Multi-language Support - English, French, and Spanish translations included
- Dynamic Language Switching - Change languages without table recreation
- Fallback System - Missing translations automatically fall back to English
- Plugin-friendly - Easy for plugin developers to add their own translations
- Number & Date Formatting - Locale-aware formatting using native
IntlAPIs - Zero Dependencies - No external i18n libraries required
- Virtual Scrolling - Handle thousands of rows with smooth scrolling
- Lazy Loading - Load data on demand for better performance
- Memory Optimization - Efficient DOM management and data handling
- Debounced Operations - Smart debouncing for search and filter operations
- Optimized Rendering - Minimal DOM updates and reflows
npm install tablixjs# Clone the repository
git clone https://github.com/ivkeapp/TablixJS.git
# Or download and include the files directly<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="./node_modules/tablixjs/dist/tablixjs.css">
</head>
<body>
<div id="my-table"></div>
<!-- UMD Build for Browser -->
<script src="./node_modules/tablixjs/dist/tablixjs.umd.min.js"></script>
<script>
const table = new TablixJS.Table('#my-table', {
data: [
{ id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' }
],
columns: [
{ name: 'id', title: 'ID', width: '60px' },
{ name: 'name', title: 'Full Name' },
{ name: 'email', title: 'Email Address' },
{
name: 'role',
title: 'User Role',
renderer: (value) => `<span class="role-badge role-${value.toLowerCase()}">${value}</span>`
}
]
});
</script>
</body>
</html>// For modern bundlers (Webpack, Vite, etc.)
import TablixJS from 'tablixjs';
const table = new TablixJS('#my-table', {
data: [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
],
columns: [
{ name: 'id', title: 'ID' },
{ name: 'name', title: 'Full Name' },
{ name: 'email', title: 'Email' }
]
});const { Table } = require('tablixjs');
// Note: TablixJS requires a DOM environment
// Use with jsdom or similar for server-side rendering<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./src/styles/tablix.css">
</head>
<body>
<div id="my-table"></div>
<script type="module">
import Table from './src/core/Table.js';
const table = new Table('#my-table', {
data: [
{ id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' }
],
columns: [
{ name: 'id', title: 'ID', width: '60px' },
{ name: 'name', title: 'Full Name' },
{ name: 'email', title: 'Email Address' },
{
name: 'role',
title: 'User Role',
renderer: (value) => `<span class="role-badge role-${value.toLowerCase()}">${value}</span>`
}
]
});
</script>
</body>
</html>TablixJS provides multiple build formats:
dist/tablixjs.umd.min.js- Minified UMD build for browsers (globalTablixJS)dist/tablixjs.esm.js- ES Module build for modern bundlersdist/tablixjs.cjs.js- CommonJS build for Node.jsdist/tablix.jquery.js- TablixJS + jQuery wrapper bundled (requires jQuery)dist/tablix-jquery-plugin.js- jQuery plugin only (requires TablixJS + jQuery loaded separately)dist/tablixjs.css- Complete CSS with all stylesdist/tablixjs-theme-dark.css- Dark themedist/tablixjs-theme-default.css- Default theme
TablixJS provides multiple jQuery integration patterns while maintaining its dependency-free core:
Single file containing both TablixJS and jQuery wrapper:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="node_modules/tablixjs/dist/tablixjs.css">
</head>
<body>
<div id="myTable"></div>
<!-- Include jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Include TablixJS with jQuery wrapper bundled -->
<script src="node_modules/tablixjs/dist/tablix.jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#myTable').tablixjs({
data: [
{ id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' }
],
columns: [
{ name: 'id', title: 'ID' },
{ name: 'name', title: 'Full Name' },
{ name: 'email', title: 'Email Address' },
{ name: 'role', title: 'User Role' }
],
pagination: { enabled: true, pageSize: 10 },
sorting: { enabled: true },
filtering: { enabled: true },
selection: { enabled: true, mode: 'multi' }
});
});Load TablixJS core and jQuery plugin separately:
<!-- Include jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Include TablixJS core -->
<script src="node_modules/tablixjs/dist/tablixjs.umd.min.js"></script>
<!-- Include jQuery plugin -->
<script src="node_modules/tablixjs/dist/tablix-jquery-plugin.min.js"></script>
<script>
// Use jQuery API
$('#myTable').tablixjs(options);
// Or mix with vanilla API
const table = new TablixJS.Table('#otherTable', options);
</script>// Import bundled jQuery version
import 'tablixjs/jquery';
// Use jQuery as normal
$('#myTable').tablixjs(options);
// Access the instance
const tableInstance = $('#myTable').data('tablixjs');
</script>
</body>
</html>// Load new data
$('#myTable').tablixJS('loadData', newDataArray);
// Get current data
var currentData = $('#myTable').tablixJS('getData');
// Get selected rows
var selectedData = $('#myTable').tablixJS('getSelectedData');
var selectedIds = $('#myTable').tablixJS('getSelectedIds');
// Selection methods
$('#myTable').tablixJS('selectRows', [1, 2, 3]);
$('#myTable').tablixJS('selectAllRows');
$('#myTable').tablixJS('clearSelection');
// Filtering and search
$('#myTable').tablixJS('applyFilter', 'status', { type: 'value', values: ['Active'] });
$('#myTable').tablixJS('setSearchTerm', 'john');
$('#myTable').tablixJS('clearAllFilters');
// Pagination
$('#myTable').tablixJS('nextPage');
$('#myTable').tablixJS('goToPage', 3);
$('#myTable').tablixJS('changePageSize', 25);
// Destroy table
$('#myTable').tablixJS('destroy');$('#myTable')
.on('tablixjs:afterLoad', function(event, data) {
console.log('Data loaded:', data);
})
.on('tablixjs:selectionChanged', function(event, selectionData) {
console.log('Selection changed:', selectionData.selectedIds);
})
.on('tablixjs:afterFilter', function(event, filterData) {
console.log('Filter applied');
});See also: jQuery Wrapper Documentation | jQuery Example Demo
import Table from './src/core/Table.js';
const table = new Table('#tableContainer', {
data: employees,
columns: [
{ name: 'name', title: 'Employee Name' },
{ name: 'department', title: 'Department' },
{ name: 'salary', title: 'Salary', renderer: (cell) => `$${cell.toLocaleString()}` }
],
pagination: {
enabled: true,
pageSize: 10,
mode: 'client', // or 'server'
showPageSizes: true,
pageSizeOptions: [5, 10, 25, 50]
},
selection: {
enabled: true, // Enable row selection
mode: 'multi', // 'single' or 'multi'
dataIdKey: 'id' // Key to use as stable row identifier
},
controls: {
enabled: true, // Automatically generate controls
pagination: true, // Show pagination controls
pageSize: true, // Show page size selector
refresh: true, // Show refresh button
position: 'top' // Controls position
}
});For advanced column formatting examples, see Column Formatting Demo and Column Formatting Usage.
TablixJS follows a modular architecture with dedicated managers for each major feature area. This design ensures clean separation of concerns, easy testing, and extensibility.
| Component | Purpose | Status |
|---|---|---|
| Table.js | Main orchestrator and public API | ✅ Complete |
| DataManager.js | Data management, filtering, and transformation | ✅ Complete |
| PaginationManager.js | Client/server pagination implementation | ✅ Complete |
| SortingManager.js | Column sorting with multi-column support | ✅ Complete |
| SelectionManager.js | Row selection with single/multi modes | ✅ Complete |
| FilterManager.js | Advanced filtering logic and conditions | ✅ Complete |
| FilterUI.js | Filter UI components and interactions | ✅ Complete |
| SearchManager.js | Global search functionality | ✅ Complete |
| Renderer.js | DOM rendering and control generation | ✅ Complete |
| EventManager.js | Event system for state tracking | ✅ Complete |
| ColumnManager.js | Column configuration and management | ✅ Complete |
| VirtualScroll.js | Virtual scrolling for large datasets | ✅ Complete |
| Wrapper | Purpose | Status |
|---|---|---|
| tablixjs-jquery.js | jQuery plugin wrapper | ✅ Complete |
| TableReact.jsx | React component wrapper | 🔄 In Progress |
| Vue Integration | Vue.js component | 📋 Planned |
| Angular Integration | Angular component | 📋 Planned |
TablixJS/
├── src/
│ ├── core/ # Core table functionality
│ │ ├── Table.js # Main API and orchestrator
│ │ ├── DataManager.js # Data management & operations
│ │ ├── PaginationManager.js # Pagination logic
│ │ ├── SortingManager.js # Column sorting
│ │ ├── SelectionManager.js # Row selection
│ │ ├── FilterManager.js # Data filtering
│ │ ├── FilterUI.js # Filter interface components
│ │ ├── SearchManager.js # Global search
│ │ ├── Renderer.js # DOM rendering
│ │ ├── EventManager.js # Event system
│ │ ├── ColumnManager.js # Column management
│ │ └── VirtualScroll.js # Virtual scrolling
│ ├── styles/ # CSS stylesheets
│ │ ├── tablix.css # Main stylesheet (imports all)
│ │ ├── table-core.css # Base table styles
│ │ ├── pagination-core.css # Pagination controls
│ │ ├── selection-core.css # Selection styling
│ │ ├── sorting-core.css # Sorting indicators
│ │ ├── filtering-core.css # Filter UI styles
│ │ ├── search-core.css # Search component
│ │ ├── virtual-scroll-core.css # Virtual scroll
│ │ └── themes/ # Theme variations
│ │ ├── default.css # Default light theme
│ │ └── dark.css # Dark theme
│ ├── jquery/ # jQuery wrapper
│ │ ├── index.js # jQuery wrapper entry point
│ │ └── tablixjs-jquery.js # jQuery plugin implementation
│ └── react/ # React wrapper
│ └── TableReact.jsx # React component
├── examples/ # Usage examples and demos
├── docs/ # Documentation files
├── LICENSE # MIT license
├── package.json # Project configuration
└── README.md # This file
import Table from './src/core/Table.js';
const table = new Table('#myTable', {
data: [
{ id: 1, name: 'John Doe', department: 'IT', salary: 75000 },
{ id: 2, name: 'Jane Smith', department: 'HR', salary: 65000 },
// ... more data
],
columns: [
{ name: 'id', title: 'ID' },
{ name: 'name', title: 'Name' },
{ name: 'department', title: 'Department' },
{ name: 'salary', title: 'Salary', renderer: (cell) => `$${cell.toLocaleString()}` }
],
pagination: {
enabled: true,
pageSize: 10,
showPageNumbers: true,
showPageSizes: true,
pageSizeOptions: [5, 10, 25, 50]
}
});
// Navigation API
await table.nextPage();
await table.prevPage();
await table.goToPage(3);
await table.changePageSize(25);
// Get pagination info
const info = table.getPaginationInfo();
console.log(`Page ${info.currentPage} of ${info.totalPages}`);async function loadDataFromServer({ page, pageSize, filters, sorts }) {
const response = await fetch(`/api/data?page=${page}&size=${pageSize}`);
const result = await response.json();
return {
data: result.items,
totalRows: result.total
};
}
const serverTable = new Table('#serverTable', {
columns: [...],
pagination: {
mode: 'server',
pageSize: 20,
serverDataLoader: loadDataFromServer,
showPageNumbers: true,
showFirstLast: true
}
});const table = new Table('#sortableTable', {
data: employees,
columns: [
{ name: 'name', title: 'Name', sortable: true },
{ name: 'age', title: 'Age', sortable: true, sortType: 'number' },
{ name: 'joinDate', title: 'Join Date', sortable: true, sortType: 'date' },
{ name: 'salary', title: 'Salary', sortable: true, sortType: 'number' }
],
sorting: {
enabled: true,
mode: 'client', // or 'server'
multiColumn: true // Allow sorting by multiple columns
}
});
// Programmatic sorting
table.sortBy('name', 'asc');
table.sortBy([
{ column: 'department', direction: 'asc' },
{ column: 'salary', direction: 'desc' }
]);const table = new Table('#filterableTable', {
data: employees,
columns: [
{ name: 'name', title: 'Name', filterable: true },
{ name: 'department', title: 'Department', filterable: true },
{ name: 'salary', title: 'Salary', filterable: true, filterType: 'number' }
],
filtering: {
enabled: true,
mode: 'client',
showBadges: true,
showTooltips: true
}
});
// Programmatic filtering
table.applyFilter('department', { type: 'value', values: ['IT', 'Engineering'] });
table.applyFilter('salary', {
type: 'condition',
operator: 'gte',
value: 50000
});const table = new Table('#searchableTable', {
data: employees,
columns: [...],
search: {
enabled: true,
placeholder: 'Search employees...',
searchDelay: 300,
caseSensitive: false
},
controls: {
search: true,
position: 'top'
}
});
// Programmatic search
table.search('john doe');
table.clearSearch();For sorting examples, see Sorting Demo and Sorting Usage Examples.
TablixJS supports flexible asynchronous data loading with multiple approaches while maintaining full backwards compatibility.
// Load data directly from an array
const data = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];
await table.loadData(data);// Load data from a REST API endpoint
await table.loadData('https://api.example.com/users');
// The API should return a JSON array:
// [
// { "id": 1, "name": "John Doe", "email": "john@example.com" },
// { "id": 2, "name": "Jane Smith", "email": "jane@example.com" }
// ]// Load with custom async function for complex scenarios
const customLoader = async () => {
const response = await fetch('/api/users', {
headers: { 'Authorization': 'Bearer ' + authToken }
});
const data = await response.json();
return data.users; // Transform if needed
};
await table.loadData(customLoader);
// Advanced example with error handling and transformation
const advancedLoader = async () => {
try {
const response = await fetch('/api/complex-data');
const rawData = await response.json();
// Transform data to match table columns
return rawData.results.map(item => ({
id: item.user_id,
name: `${item.first_name} ${item.last_name}`,
email: item.email_address,
department: item.dept?.name || 'Unknown'
}));
} catch (error) {
throw new Error('Failed to load user data');
}
};
await table.loadData(advancedLoader);// Show loading indicators
table.on('beforeLoad', (payload) => {
console.log('Loading started from:', typeof payload.source);
if (typeof payload.source === 'string' || typeof payload.source === 'function') {
showLoadingSpinner();
}
});
// Handle successful loading
table.on('afterLoad', (payload) => {
console.log(`Loaded ${payload.data.length} records`);
hideLoadingSpinner();
});
// Handle loading errors
table.on('loadError', (payload) => {
console.error('Loading failed:', payload.error.message);
hideLoadingSpinner();
showErrorMessage(payload.error.message);
});Learn More: See Async Data Loading Guide for complete documentation and live demo.
import { frenchTranslations } from './src/locales/fr.js';
import { spanishTranslations } from './src/locales/es.js';
const table = new Table('#multiLangTable', {
data: employees,
columns: [...],
language: 'fr',
translations: {
fr: frenchTranslations,
es: spanishTranslations
},
pagination: {
enabled: true,
pageSize: 10
},
selection: {
enabled: true,
mode: 'multi'
}
});
// Dynamic language switching
table.setLanguage('es'); // Switch to Spanish
table.setLanguage('fr'); // Switch to French
// Add custom translations
table.addTranslations('de', {
'pagination.next': 'Nächste',
'pagination.previous': 'Vorherige',
'search.placeholder': 'Suchen...'
});
// Use translations in your code
console.log(table.t('pagination.next')); // "Suivant" in French
console.log(table.t('pagination.showingRecords', {
startRow: 1, endRow: 10, totalRows: 100
})); // "Affichage de 1 à 10 sur 100 enregistrements"
// Format numbers with locale
const price = table.formatNumber(1234.56, { style: 'currency', currency: 'EUR' });
console.log(price); // "1 234,56 €" in French locale### **Event System**
```javascript
// Pagination events
table.on('afterPageChange', ({ oldPage, newPage }) => {
console.log(`Navigated from page ${oldPage} to ${newPage}`);
});
table.on('beforePageLoad', ({ page, pageSize }) => {
console.log('Loading data from server...');
});
// Filter integration
table.on('afterFilter', (criteria) => {
console.log('Filtered, reset to page 1');
});
// Search events
table.on('afterSearch', ({ query, results }) => {
console.log(`Search for "${query}" returned ${results.length} results`);
});
// Sorting events
table.on('afterSort', ({ column, direction }) => {
console.log(`Sorted by ${column} in ${direction} order`);
});Learn More: For filtering examples, see Filtering Demo and Filtering Usage Examples.
TablixJS includes powerful row selection functionality with support for both single and multi-row selection modes.
const table = new Table('#tableContainer', {
data: employees,
columns: [...],
selection: {
enabled: true, // Enable selection (default: false)
mode: 'multi', // 'single' or 'multi' (default: 'single')
dataIdKey: 'id' // Key to use as stable row identifier
}
});- Click any row to select it
- Previous selection is automatically cleared
- Click selected row to deselect it
- Normal click: Select row (clears other selections)
- Ctrl+Click: Toggle individual row selection
- Shift+Click: Select range from last selected row
- Drag Selection: Click and drag to select multiple consecutive rows
- Click selected row: Deselect if it's the only selected row
// Get selection information
const selectedData = table.getSelectedData(); // Array of row objects
const selectedIds = table.getSelectedIds(); // Array of row IDs
const count = table.getSelectionCount(); // Number of selected rows
// Check if specific row is selected
const isSelected = table.isRowSelected('123');
// Programmatic selection
table.selectRows(['1', '3', '5']); // Select specific rows by ID
table.selectRows('2'); // Select single row
table.deselectRows(['1', '3']); // Deselect specific rows
table.clearSelection(); // Clear all selections
// Enable/disable selection
table.enableSelection();
table.disableSelection();
table.setSelectionMode('single'); // Change mode dynamically// Before selection changes
table.eventManager.on('beforeSelect', (event) => {
console.log('About to select:', event.rowData);
console.log('Current selection:', event.currentSelection);
// Optionally prevent selection by throwing an error
// if (event.rowData.locked) throw new Error('Row is locked');
});
// After selection changes
table.eventManager.on('afterSelect', (event) => {
console.log('Selected rows:', event.selectedRows);
console.log('Selected data:', event.selectedData);
// Update UI based on selection
updateToolbar(event.selectedData);
});Selection automatically works with all table features:
- Pagination: Selection persists across page changes
- Filtering: Rows hidden by filters are automatically deselected
- Sorting: Selection follows the data (uses stable row IDs)
- Data Updates: Selection is preserved when data is reloaded
Learn More: For a complete interactive demo, see Selection Demo and Selection Usage Examples.
- Basic Usage - Simple client-side pagination
- Async Data Loading Demo - Asynchronous data loading examples
- Column Formatting Demo - Custom column formatting
- Complete Pagination Demo - All pagination features
- Filtering Demo - Data filtering capabilities
- Selection Demo - Row selection functionality 🆕
- Drag Selection Demo - Advanced drag-to-select functionality 🔥
- Localization Demo - Multi-language support and dynamic language switching ⭐
- Auto Controls - Automatic control generation
- Theme Demo - Theming and styling examples
- Sorting Demo - Column sorting functionality
- Pagination Samples - Implementation patterns
- jQuery Integration - jQuery wrapper usage
- React Integration - React component usage
TablixJS comes with a comprehensive theming system built on CSS custom properties, making it easy to customize the appearance while maintaining consistency.
Include the main stylesheet in your HTML:
<link rel="stylesheet" href="./src/styles/tablix.css">Light Theme (Default)
<html data-theme="light">
<!-- or -->
<div class="tablix-wrapper light">Dark Theme
<html data-theme="dark">
<!-- or -->
<div class="tablix-wrapper dark">Create custom themes using CSS custom properties:
.my-custom-theme {
/* Table colors */
--tablix-bg: #f8f9fa;
--tablix-border-color: #dee2e6;
--tablix-text-color: #212529;
/* Header styling */
--tablix-header-bg: #e9ecef;
--tablix-header-text-color: #495057;
--tablix-header-border-color: #adb5bd;
/* Row styling */
--tablix-row-even-bg: #ffffff;
--tablix-row-odd-bg: #f8f9fa;
--tablix-row-hover-bg: #e3f2fd;
/* Selection colors */
--tablix-row-selected-bg: #cce5ff;
--tablix-row-selected-hover-bg: #b3d9ff;
--tablix-row-last-selected-bg: #007bff;
--tablix-row-last-selected-color: #ffffff;
/* Control styling */
--tablix-btn-bg: #007bff;
--tablix-btn-text-color: #ffffff;
--tablix-btn-hover-bg: #0056b3;
--tablix-btn-disabled-bg: #6c757d;
/* Sort indicators */
--tablix-sort-indicator-color: #6c757d;
--tablix-sort-active-color: #007bff;
}Pagination Controls
.tablix-pagination {
--tablix-pagination-gap: 0.5rem;
--tablix-pagination-btn-padding: 0.375rem 0.75rem;
--tablix-pagination-btn-border-radius: 0.25rem;
}Filter UI
.tablix-filter-dropdown {
--tablix-filter-dropdown-bg: #ffffff;
--tablix-filter-dropdown-border: 1px solid #ced4da;
--tablix-filter-dropdown-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}Search Component
.tablix-search {
--tablix-search-input-bg: #ffffff;
--tablix-search-input-border: 1px solid #ced4da;
--tablix-search-input-focus-border: #007bff;
}TablixJS includes responsive breakpoints and mobile-friendly features:
Tables automatically wrap with horizontal scrolling for mobile devices:
<!-- Automatic structure for mobile support -->
<div class="tablix-wrapper">
<div class="tablix-controls"><!-- stays visible --></div>
<div class="tablix-table-wrapper" style="overflow-x: auto;">
<table class="tablix-table"><!-- scrolls horizontally --></table>
</div>
<div class="tablix-pagination-container"><!-- stays visible --></div>
</div>This ensures controls remain accessible while wide tables scroll horizontally on small screens. See Mobile Responsive Design for details.
/* Mobile styles (< 768px) */
@media (max-width: 767.98px) {
.tablix-wrapper {
--tablix-font-size: 0.875rem;
--tablix-cell-padding: 0.5rem;
}
.tablix-pagination {
--tablix-pagination-gap: 0.25rem;
--tablix-pagination-btn-padding: 0.25rem 0.5rem;
}
}
/* Tablet styles (768px - 991.98px) */
@media (min-width: 768px) and (max-width: 991.98px) {
.tablix-wrapper {
--tablix-font-size: 0.9375rem;
}
}Add custom classes through configuration:
const table = new Table('#table', {
// ... other options
cssClasses: {
wrapper: ['my-table-wrapper', 'custom-theme'],
table: ['my-table'],
headerRow: ['my-header'],
dataRow: ['my-row'],
selectedRow: ['my-selected-row']
}
});// Switch themes programmatically
function switchTheme(themeName) {
document.documentElement.setAttribute('data-theme', themeName);
// Or update CSS classes
const wrapper = document.querySelector('.tablix-wrapper');
wrapper.className = `tablix-wrapper ${themeName}`;
}
// Theme switcher UI
const themeSelector = document.getElementById('theme-selector');
themeSelector.addEventListener('change', (e) => {
switchTheme(e.target.value);
});Learn More: See the Theming Guide for complete customization options and the Theme Demo for interactive examples.
# Clone the repository
git clone https://github.com/ivkeapp/TablixJS.git
cd TablixJS
# Start development server (requires Node.js)
npm run dev
# Open your browser to:
# http://localhost:5174- 🏠 Example Index - Main examples page with all demos
- ⚡ Basic Demo - Start here for basic usage
- 🎯 Complete Demo - Full feature showcase
- 🎮 Playground - Interactive configuration tool
For production, simply include the files directly (no build process required):
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="path/to/tablix/src/styles/tablix.css">
</head>
<body>
<div id="my-table"></div>
<script type="module">
import Table from 'path/to/tablix/src/core/Table.js';
// Your table code here...
</script>
</body>
</html>- Basic Usage - Simple client-side pagination setup
- Auto Controls - Automatic control generation
- Complete Pagination - All pagination features
- Async Data Loading - Asynchronous data loading examples
- Server-side Integration - Server-side pagination and filtering
- Row Selection - Single and multi-row selection 🆕
- Drag Selection - Advanced drag-to-select functionality ⭐
- Sorting - Column sorting with multi-column support
- Filtering - Advanced filtering capabilities
- Search - Global search functionality
- Column Formatting - Custom column formatting and renderers
- Theme Demo - Theming and styling examples
- Localization Demo - Multi-language support with language switching ⭐
- Virtual Scrolling - Handle large datasets efficiently
- Virtual Scroll Test Suite - Performance testing
- jQuery Integration - jQuery wrapper usage
- React Integration - React component usage
- Async Loading Test - Async functionality testing
- Virtual Scroll Bugfix Test - Bug testing scenarios
- Pagination API - Complete pagination guide with examples
- Async Data Loading - Asynchronous data loading patterns
- Selection Guide - Row selection functionality and API
- Filtering - Advanced data filtering documentation
- Sorting - Column sorting with multi-column support
- Simple Sorting - Basic sorting implementation
- Virtual Scrolling - Virtual scrolling for large datasets
- Virtual Scroll Bugfixes - Known issues and fixes
- Localization System - Comprehensive internationalization guide ⭐
- Theming Guide - CSS customization and theme system
- Column Formatting - Custom column formatting and renderers
- Plugin Architecture - Extending TablixJS functionality
Test the production-ready built version with our comprehensive example:
# Build the library
npm run build
# Start local server
npm run dev
# Navigate to: http://localhost:5174/examples/built-version-test.htmlFeatures Tested:
- ✅ All module formats (ESM, CJS, UMD)
- ✅ Data loading (static & async)
- ✅ Pagination with dynamic page sizes
- ✅ Multi-column sorting
- ✅ Advanced filtering and search
- ✅ Row selection (single & multi)
- ✅ Virtual scrolling with 10K+ rows
- ✅ Theme switching (default & dark)
- ✅ Performance monitoring
- ✅ Event system validation
Explore individual features with focused examples:
- Complete Features Demo - All features in production build
- Pagination Examples - Advanced pagination patterns
- Selection Demo - Interactive selection modes
- Virtual Scrolling - Large dataset performance
- Filtering Demo - Advanced filtering UI
- Theming Demo - Theme customization
💡 Pro Tip: Use
examples/built-version-test.htmlto verify everything works after making changes to the library!
// Constructor
new Table(container, options)
// Data methods
table.loadData(data) // Load data (array, URL, or function)
table.getData() // Get current data
table.getFilteredData() // Get filtered data
table.refreshData() // Reload data from source
// Pagination methods
table.nextPage() // Go to next page
table.prevPage() // Go to previous page
table.goToPage(page) // Go to specific page
table.changePageSize(size) // Change page size
table.getPaginationInfo() // Get pagination state
// Selection methods
table.selectRows(ids) // Select rows by ID
table.deselectRows(ids) // Deselect rows by ID
table.clearSelection() // Clear all selections
table.getSelectedData() // Get selected row data
table.getSelectedIds() // Get selected row IDs
table.getSelectionCount() // Get selection count
// Sorting methods
table.sortBy(column, direction) // Sort by column
table.clearSort() // Clear sorting
table.getSortState() // Get current sort state
// Filtering methods
table.applyFilter(column, filter) // Apply column filter
table.clearFilter(column) // Clear column filter
table.clearAllFilters() // Clear all filters
table.getFilterState() // Get current filter state
// Search methods
table.search(query) // Apply global search
table.clearSearch() // Clear search
table.getSearchQuery() // Get current search query
// Localization methods
table.t(key, params) // Get translated string
table.setLanguage(language) // Change current language
table.addTranslations(lang, obj) // Add language translations
table.getCurrentLanguage() // Get current language
table.formatNumber(num, options) // Format number with locale
table.formatDate(date, options) // Format date with locale
// Event methods
table.on(event, callback) // Add event listener
table.off(event, callback) // Remove event listener
table.emit(event, data) // Emit custom event| Feature | Small Dataset (< 1,000 rows) | Medium Dataset (1,000-10,000 rows) | Large Dataset (10,000+ rows) |
|---|---|---|---|
| Client-side Pagination | Instant | < 100ms | Use Virtual Scrolling |
| Server-side Pagination | Instant | Instant | Instant |
| Column Sorting | < 50ms | < 200ms | < 500ms |
| Global Search | < 10ms | < 100ms | < 300ms |
| Row Selection | Instant | Instant | Instant |
| Virtual Scrolling | N/A | < 50ms | < 100ms |
- Use Server-side Pagination for datasets larger than 10,000 rows
- Enable Virtual Scrolling for client-side tables with 1,000+ rows
- Debounce Search to reduce unnecessary filtering operations
- Use Row IDs for stable selection across data operations
- Lazy Load Data when possible to reduce initial page load time
- Optimize Renderers to avoid complex DOM operations in cell renderers
- Client-side Mode: Keeps all data in memory for fast operations
- Server-side Mode: Only current page data in memory
- Virtual Scrolling: Renders only visible rows + buffer
- Selection State: Minimal memory footprint using row IDs
Problem: Global TablixJS object is not available when using UMD build.
ReferenceError: TablixJS is not definedSolution:
- Ensure correct script tag order and file paths
- Add charset declaration to prevent encoding issues
<meta charset="UTF-8">
<script src="./node_modules/tablixjs/dist/tablixjs.umd.min.js"></script>
<script>
const table = new TablixJS.Table('#container', options);
</script>Problem: CommonJS/ESM module conflicts in Node.js.
ReferenceError: exports is not definedSolution:
- Use ES modules with
importfor"type": "module"packages - Use CommonJS with
require()for standard packages
// ESM (when "type": "module" in package.json)
import TablixJS from 'tablixjs';
// CommonJS (standard Node.js)
const { Table } = require('tablixjs');Problem: TablixJS requires DOM environment, not available in Node.js.
ReferenceError: document is not definedSolution: TablixJS is browser-focused. For Node.js testing:
npm install jsdomimport { JSDOM } from 'jsdom';
const dom = new JSDOM('<!DOCTYPE html><div id="table"></div>');
global.document = dom.window.document;
global.window = dom.window;Problem: CI/CD failing with npm ci requiring package-lock.json.
npm error The `npm ci` command can only install with an existing package-lock.jsonSolution:
- Remove
package-lock.jsonfrom.gitignore - Commit
package-lock.jsonto repository - Regenerate if needed:
rm package-lock.json && npm install
Problem: PowerShell commands failing in Linux CI environments.
sh: 1: powershell: not foundSolution: Use cross-platform Node.js commands:
{
"scripts": {
"copy:types": "node -e "require('fs').copyFileSync('src/index.d.ts', 'dist/index.d.ts')"",
"clean": "node -e "require('fs').rmSync('dist', {recursive: true, force: true})""
}
}Problem: Using outdated action versions.
Error: This request has been automatically failed because it uses a deprecated version of `actions/upload-artifact: v3`Solution: Update to latest versions:
- uses: actions/upload-artifact@v4 # not v3
- uses: actions/checkout@v4 # not v3Problem: Unicode characters displaying as garbled text (⟳ instead of ⟳). Solution: Add proper charset declaration:
<meta charset="UTF-8">Problem: "querySelector is not a function" errors.
TypeError: this.table.container.querySelector is not a functionSolution: Ensure container parameter is correct:
// Correct API
new TablixJS.Table('#container', options); // selector string
new TablixJS.Table(document.getElementById('container'), options); // DOM element
// Incorrect
new TablixJS.Table({ container: '#container', ...options }); // wrong structureProblem: "Column must have a 'name' property" error.
Error: TablixJS: Column must have a "name" propertySolution: Use name property, not key:
// Correct
columns: [
{ name: 'id', title: 'ID' }, // ✓ 'name'
{ name: 'email', title: 'Email' } // ✓ 'name'
]
// Incorrect
columns: [
{ key: 'id', title: 'ID' }, // ✗ 'key'
{ key: 'email', title: 'Email' } // ✗ 'key'
]Problem: Disabled pagination still shows controls, table doesn't show all data. Solution: Re-initialize table when changing pagination state:
function togglePagination() {
paginationEnabled = !paginationEnabled;
const currentData = table.getOriginalData();
initializeTable(currentData, {
pagination: { enabled: paginationEnabled }
});
}Problem: Both virtual scrolling and pagination active simultaneously. Solution: Make features mutually exclusive:
if (paginationEnabled && virtualScrollEnabled) {
virtualScrollEnabled = false; // Disable conflicting feature
}Problem: Dark theme not applying properly.
Solution: Apply data-theme attribute for CSS custom properties:
function switchTheme(theme) {
document.body.removeAttribute('data-theme');
if (theme !== 'default') {
document.body.setAttribute('data-theme', theme);
}
// Load theme CSS file...
}Problem: Selection buttons clickable when selection is disabled. Solution: Update control states and disable buttons:
function updateControlStates() {
const selectAllBtn = document.querySelector('[onclick="selectAll()"]');
if (selectAllBtn) {
selectAllBtn.disabled = !selectionEnabled;
selectAllBtn.className = selectionEnabled ? 'secondary' : 'secondary disabled';
}
}Problem: Browser freezing with 1000+ rows. Solution: Enable virtual scrolling:
const table = new TablixJS.Table('#container', {
data: largeDataset,
virtualScroll: {
enabled: true,
buffer: 10,
containerHeight: 400
},
pagination: { enabled: false } // Disable for virtual scroll
});Problem: Typing causes performance issues. Solution: Increase debounce delay:
search: {
enabled: true,
searchDelay: 500 // Increase from default 300ms
}Problem: Examples not loading properly. Solution: Use proper development server:
# Method 1: Project dev server
npm run dev
# Method 2: Static file server
npx serve . -l 8080
# Method 3: Python (if available)
python -m http.server 8000Problem: ES modules not loading in browser. Solution: Ensure proper server setup and file extensions:
<!-- Use type="module" for ES modules -->
<script type="module">
import Table from './src/core/Table.js'; // Include .js extension
</script>When reporting issues, please include:
- Browser version and operating system
- Node.js version (for build issues)
- Complete error messages from browser console
- Minimal code example that reproduces the issue
- TablixJS version being used
Useful debugging commands:
# Check build output
npm run build
ls -la dist/
# Verify package contents
npm pack --dry-run
# Check for console errors
# Open browser DevTools → Console tab
# Performance debugging
# DevTools → Performance tab → RecordWe welcome contributions to TablixJS! Here's how you can help:
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/TablixJS.git cd TablixJS - Create a feature branch:
git checkout -b feature/your-feature-name
- Follow the modular architecture - each feature should have its own manager
- Write comprehensive tests for new functionality
- Update documentation for any API changes
- Ensure examples work with your changes
- Follow ES6+ standards and use modern JavaScript features
- Maintain backwards compatibility when possible
# Start the development server
npm run dev
# Test your changes in the browser
open http://localhost:5174/examples/- Test thoroughly - verify all examples work
- Update documentation if needed
- Commit your changes with descriptive messages
- Push to your fork and create a Pull Request
- Describe your changes in the PR description
- Issues: Use GitHub Issues for bug reports and feature requests
- Discussions: Use GitHub Discussions for questions and ideas
- Security: Report security issues privately via email
TablixJS is released under the MIT License. See LICENSE file for details.
- ✅ Core table functionality with pagination
- ✅ Row selection (single/multi modes)
- ✅ Column sorting and filtering
- ✅ Global search functionality
- ✅ Async data loading
- ✅ Theming system
- ✅ Virtual scrolling
- ✅ Localization system with multi-language support
- 🔄 Enhanced jQuery wrapper
- 🔄 Complete React component
- 📋 Vue.js integration
- 📋 Angular component wrapper
- 📋 TypeScript definitions
- 📋 Export functionality (CSV, Excel, PDF)
- 📋 Column reordering via drag & drop
- 📋 Inline editing capabilities
- Plugin System: Extensible plugin architecture
- Advanced Filtering: Date ranges, regex, custom operators
- Column Groups: Grouped column headers
- Row Grouping: Hierarchical data grouping
- Frozen Columns: Pin columns to left/right
- Accessibility: Enhanced ARIA support and keyboard navigation
- Performance: Web Workers for large dataset operations
🌟 Star us on GitHub if TablixJS helps your project!
Built with ❤️ by Ivan Zarkovic, AI and contributors.