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
});