A comprehensive table library with freeze headers/columns, export functionality, lazy loading, server-side processing, custom context menu, and customizable styling.
const basicTable = new Tabelin({ container: '#basic-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'age', title: 'Age' }, { field: 'email', title: 'Email' } ], data: generateDemoData(20) });
const freezeTable = new Tabelin({ container: '#freeze-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'department', title: 'Department' }, { field: 'position', title: 'Position' }, { field: 'salary', title: 'Salary' }, { field: 'startDate', title: 'Start Date' }, { field: 'email', title: 'Email' } ], data: generateDemoData(50), freezeHeader: true, freezeColumns: 2 });
const paginationTable = new Tabelin({ container: '#pagination-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'email', title: 'Email' } ], data: generateDemoData(100), pageSize: 10 });
Scroll down in the table below to load more data automatically without pagination. The data will continue loading as you scroll.
// Using the convenient static method const lazyLoadingTable = Tabelin.createInfiniteTable( '#lazy-loading-table-container', [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'email', title: 'Email' }, { field: 'department', title: 'Department' } ], generateDemoData(500), { batchSize: 15, loadThreshold: 100, freezeHeader: true } ); // Equivalent to: new Tabelin({ container: '#lazy-loading-table-container', columns: [...], data: generateDemoData(500), infiniteScroll: true, pageSize: 15, loadThreshold: 100, freezeHeader: true });
Create an advanced table from an existing HTML table structure:
ID | First Name | Last Name | Position | Department |
---|---|---|---|---|
1 | John | Smith | Manager | Engineering |
2 | Jane | Doe | Developer | Engineering |
3 | Mike | Johnson | Designer | Marketing |
4 | Lisa | Brown | Director | HR |
5 | David | Williams | Analyst | Finance |
// Using the convenient static method const htmlTable = Tabelin.fromHTML('#existing-table', { freezeHeader: true, freezeColumns: 1, searchable: true, sortable: true, exportOptions: { excel: true, pdf: true, print: true } }); // Equivalent to: new Tabelin({ container: '#html-table-container', useHTML: '#existing-table', freezeHeader: true, freezeColumns: 1, searchable: true, sortable: true, exportOptions: { excel: true, pdf: true, print: true } });
This example simulates a server-side data source with search, sorting, and pagination functionality.
These controls simulate server-side behavior for the demo.
// Using the convenient static method const serverTable = Tabelin.createServerTable( '#server-table-container', [ { field: 'id', title: 'ID', sortable: true }, { field: 'name', title: 'Name', sortable: true }, { field: 'email', title: 'Email' }, { field: 'department', title: 'Department', sortable: true }, { field: 'position', title: 'Position', sortable: true } ], 'api/table-data', { pageSize: 10, searchable: true, sortable: true, // Custom server params function serverParams: function(params) { return { // Add any additional params your server needs token: 'demo-token', customParam: 'any-value' }; } } );
This example simulates an infinitely scrolling server-side data source.
const serverLazyTable = new Tabelin({ container: '#server-lazy-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'email', title: 'Email' }, { field: 'department', title: 'Department' } ], pageSize: 20, serverSide: true, serverUrl: 'api/lazy-data', infiniteScroll: true, loadThreshold: 200, searchable: true });
const themedTable = new Tabelin({ container: '#theme-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'department', title: 'Department' }, { field: 'position', title: 'Position' } ], data: generateDemoData(20), theme: 'material', // Choose from: 'default', 'dark', 'stripe', 'material', 'compact', 'colorful' searchable: true });
You can apply your own CSS classes and styles to the table:
// Define custom CSS variables and styles in your stylesheet .custom-theme-table { --header-bg: #3f51b5; --header-text: white; --row-hover: #f0f4ff; --border-color: #c5cae9; --accent-color: #3f51b5; } // Then apply the custom class to your table const customStyledTable = new Tabelin({ container: '#custom-style-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'department', title: 'Department' }, { field: 'position', title: 'Position' } ], data: generateDemoData(15), cssClass: 'custom-theme-table', // Customize row and cell styles with callbacks rowClassName: function(row, index) { return index % 2 === 0 ? 'even-row' : 'odd-row'; }, cellClassName: function(value, row, column, colIndex) { if (column.field === 'department' && value === 'Engineering') { return 'highlight-cell'; } return ''; } });
const customRenderTable = new Tabelin({ container: '#custom-render-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'status', title: 'Status', render: (value, row) => { const color = value === 'Active' ? 'green' : 'red'; return `${value}`; } }, { field: 'progress', title: 'Progress', render: (value, row) => { const percent = parseInt(value); return ` ${percent}% `; } }, { field: 'actions', title: 'Actions', render: (value, row) => { return ` `; } } ], data: generateDemoData(20).map(item => ({ ...item, status: Math.random() > 0.5 ? 'Active' : 'Inactive', progress: Math.floor(Math.random() * 100) })), searchable: true, resizableColumns: true });
Double-click on any cell in the table to edit its value. Changes are tracked with version history.
const editableTable = new Tabelin({ container: '#editable-table-container', columns: [ { field: 'id', title: 'ID', editable: false }, { field: 'name', title: 'Name' }, { field: 'department', title: 'Department' }, { field: 'salary', title: 'Salary' } ], data: generateDemoData(10), // Enable cell editing collaboration: true, collaborationMode: 'local', // 'local', 'websocket', 'polling' collaborationUser: { name: 'John', id: 1, color: '#4CAF50' }, // Enable version history versionHistory: true, maxVersions: 10, // Add note telling users how to access version history footnote: 'Double-click to edit cells. Right-click and select "View Version History" to see changes.' });
This example demonstrates integrated data visualizations with our table library.
const visualizationsTable = new Tabelin({ container: '#visualizations-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'sales', title: 'Sales' }, { field: 'growth', title: 'Growth %' }, { field: 'profit', title: 'Profit' } ], data: generateSalesData(30), visualizations: true, visualizationPosition: 'summary', visualizationTypes: ['bar', 'line', 'pie', 'sparkline'], visualizationColors: ['#4CAF50', '#2196F3', '#FFC107', '#F44336', '#9C27B0'], // Enable AI insights to analyze data patterns aiInsights: true, theme: 'material' }); // Generate sample sales data function generateSalesData(count) { const data = []; const regions = ['North', 'South', 'East', 'West', 'Central']; const products = ['Widgets', 'Gadgets', 'Devices', 'Tools', 'Accessories']; for (let i = 1; i <= count; i++) { const sales = 10000 + Math.floor(Math.random() * 90000); const growth = -10 + Math.floor(Math.random() * 40); const profit = sales * (0.15 + Math.random() * 0.25); // 15-40% profit margin data.push({ id: i, name: `${regions[i % regions.length]} - ${products[i % products.length]}`, sales: sales, growth: growth, profit: Math.round(profit) }); } return data; }
Apply formatting rules based on cell values:
const formattingTable = new Tabelin({ container: '#formatting-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'department', title: 'Department' }, { field: 'salary', title: 'Salary' }, { field: 'performance', title: 'Performance' }, { field: 'startDate', title: 'Start Date' }, { field: 'email', title: 'Email', width: 200 } ], data: generateDemoData(15).map(item => ({ ...item, performance: ['Poor', 'Average', 'Good', 'Excellent'][Math.floor(Math.random() * 4)] })), // Enable conditional formatting conditionalFormatting: true, rules: [ { field: 'salary', condition: value => value > 80000, style: { backgroundColor: '#e8f5e9', fontWeight: 'bold', color: '#2e7d32' } }, { field: 'salary', condition: value => value < 40000, style: { backgroundColor: '#ffebee', color: '#c62828' } }, { field: 'performance', condition: value => value === 'Excellent', style: { backgroundColor: '#e3f2fd', fontWeight: 'bold', color: '#1565c0' } }, { field: 'performance', condition: value => value === 'Poor', style: { backgroundColor: '#ffebee', fontStyle: 'italic', color: '#b71c1c' } } ], // Enable smart formatting smartFormatting: true, formatDetection: { numbers: true, // Auto-format numbers (currency, percentages, etc.) dates: true, // Auto-format dates urls: true, // Auto-format URLs as links emails: true // Auto-format emails as mailto links } });
Apply business rules and validation to your data:
const validationTable = new Tabelin({ container: '#validation-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'email', title: 'Email' }, { field: 'age', title: 'Age' }, { field: 'salary', title: 'Salary' } ], data: generateDemoData(10), // Make cells editable collaboration: true, // Enable validation for edits validateOnEdit: true, showValidationMessages: true, // Define business rules businessRules: [ { field: 'email', rule: value => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value), message: 'Please enter a valid email address' }, { field: 'age', rule: value => value >= 18 && value <= 65, message: 'Age must be between 18 and 65' }, { field: 'salary', rule: value => value >= 30000, message: 'Salary must be at least $30,000' }, { field: 'name', rule: value => value.length >= 2, message: 'Name must be at least 2 characters' } ] });
Automatically analyze data patterns and display insights:
const insightsTable = new Tabelin({ container: '#insights-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'department', title: 'Department' }, { field: 'salary', title: 'Salary' }, { field: 'salesTarget', title: 'Sales Target' }, { field: 'salesActual', title: 'Sales Actual' } ], data: generateInsightData(50), // Enable AI insights aiInsights: true, insightsPosition: 'top', // 'top', 'bottom', 'tooltip' insightsThreshold: 0.7, // Confidence threshold // Add other options searchable: true, sortable: true, theme: 'material' }); // Generate sample data with patterns for insights to detect function generateInsightData(count) { const departments = ['Sales', 'Marketing', 'Engineering', 'HR', 'Finance']; const data = []; for (let i = 1; i <= count; i++) { const department = departments[Math.floor(Math.random() * departments.length)]; const baseSalary = department === 'Sales' ? 55000 : department === 'Engineering' ? 75000 : department === 'Marketing' ? 60000 : department === 'Finance' ? 70000 : 50000; // Create salary variations within departments const salary = baseSalary + Math.floor(Math.random() * 30000); // Generate sales targets and actuals with meaningful relationship const salesTarget = department === 'Sales' ? 100000 + Math.floor(Math.random() * 50000) : 0; // Create a pattern: half of sales people exceed targets, half don't const performance = Math.random() > 0.5 ? 1.2 : 0.8; const salesActual = department === 'Sales' ? Math.floor(salesTarget * performance) : 0; const demoUser = generateDemoData(1)[0]; data.push({ ...demoUser, department, salary, salesTarget, salesActual }); } // Add some outliers and patterns for the AI to detect if (data.length > 10) { data[3].salary = 150000; // Outlier data[7].salary = 25000; // Outlier // Pattern: make everyone in marketing have better sales performance data.forEach(item => { if (item.department === 'Marketing' && item.salesTarget > 0) { item.salesActual = Math.floor(item.salesTarget * 1.3); } }); } return data; }
View statistical distribution of your numeric data:
const distributionTable = new Tabelin({ container: '#distribution-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'age', title: 'Age' }, { field: 'experience', title: 'Experience (Years)' }, { field: 'salary', title: 'Salary' }, { field: 'performance', title: 'Performance Score' } ], data: generateDistributionData(100), // Enable visualizations with distribution charts visualizations: true, visualizationPosition: 'summary', visualizationTypes: ['distribution'], // Add other features searchable: true, sortable: true }); // Generate normally distributed data function generateDistributionData(count) { function normalRandom(mean, stdDev) { // Box-Muller transform for normal distribution const u1 = Math.random(); const u2 = Math.random(); const z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(2.0 * Math.PI * u2); return z0 * stdDev + mean; } const data = []; for (let i = 1; i <= count; i++) { const age = Math.round(normalRandom(35, 8)); const experience = Math.max(0, Math.round(normalRandom(age - 22, 5))); // experience related to age const performance = Math.min(100, Math.max(0, Math.round(normalRandom(70, 15)))); // performance score 0-100 // Salary based on experience and performance const baseSalary = 40000 + (experience * 2000); const performanceBonus = performance * 200; const salary = Math.round(baseSalary + performanceBonus); const demoUser = generateDemoData(1)[0]; data.push({ ...demoUser, age, experience, performance, salary }); } return data; }
const searchSortTable = new Tabelin({ container: '#search-sort-table-container', columns: [ { field: 'id', title: 'ID', sortable: true }, { field: 'name', title: 'Name', sortable: true }, { field: 'department', title: 'Department', sortable: true }, { field: 'salary', title: 'Salary', sortable: true }, { field: 'startDate', title: 'Start Date', sortable: false } ], data: generateDemoData(50), searchable: true, sortable: true });
Navigate the table using keyboard shortcuts:
const keyboardNavTable = new Tabelin({ container: '#keyboard-nav-table-container', columns: [ { field: 'id', title: 'ID' }, { field: 'name', title: 'Name' }, { field: 'email', title: 'Email' }, { field: 'department', title: 'Department' }, { field: 'position', title: 'Position' } ], data: generateDemoData(15), // Enable keyboard navigation keyboardNavigation: true, keyboardShortcuts: true, // Accessibility features accessibleHeaders: true, focusableRows: true, ariaLabels: { table: 'Employee Data Table', search: 'Search employee records', pagination: 'Table pagination controls', sortAsc: 'Sort column ascending', sortDesc: 'Sort column descending', row: index => `Employee record ${index + 1}` }, // Make table cells editable collaboration: true });