UNPKG

vanillajs-excelike-table

Version:

A user-friendly pure JavaScript table library with Excel-like features, preset configurations, and intuitive column helpers. Vanilla JS implementation - no frameworks required!

350 lines (317 loc) 11.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>VanillaJS ExceLike Table - Full Featured Demo</title> <link rel="stylesheet" href="../src/ExceLikeTable.css"> <style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; } .container { max-width: 1200px; margin: 0 auto; background: white; padding: 24px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } h1 { color: #1890ff; margin-bottom: 20px; text-align: center; } .demo-section { margin-bottom: 24px; } .demo-controls { display: flex; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; } .demo-btn { padding: 8px 16px; border: 1px solid #d9d9d9; background: white; border-radius: 4px; cursor: pointer; transition: all 0.2s; font-size: 14px; } .demo-btn:hover { border-color: #1890ff; color: #1890ff; } .demo-btn.primary { background: #1890ff; color: white; border-color: #1890ff; } .demo-btn.primary:hover { background: #40a9ff; } .table-container { height: 600px; border: 1px solid #d9d9d9; border-radius: 4px; } .info-panel { background: #f9f9f9; padding: 16px; border-radius: 4px; margin-bottom: 16px; } .info-panel h3 { margin: 0 0 8px 0; color: #1890ff; } .info-panel ul { margin: 0; padding-left: 20px; } .info-panel li { margin-bottom: 4px; } </style> </head> <body> <div class="container"> <h1>🚀 VanillaJS ExceLike Table - Full Featured Demo with Settings Persistence</h1> <div class="info-panel"> <h3>Features Demonstrated:</h3> <ul> <li><strong>Filtering:</strong> Text search, numeric range sliders, date hierarchy</li> <li><strong>Sorting:</strong> Click column headers to sort ascending/descending</li> <li><strong>Column Pinning:</strong> Pin columns to left side with sticky positioning</li> <li><strong>Column Visibility:</strong> Show/hide columns via settings menu</li> <li><strong>Pagination:</strong> Navigate through large datasets with configurable page sizes</li> <li><strong>Responsive Design:</strong> Works on desktop and mobile devices</li> <li><strong>Column Resizing:</strong> Drag column borders to resize widths</li> <li><strong>🆕 Settings Persistence:</strong> All settings automatically saved to LocalStorage and restored on page reload</li> </ul> </div> <div class="info-panel" style="background: #e6f7ff; border-left: 4px solid #1890ff;"> <h3>💾 Settings Persistence Feature:</h3> <ul> <li><strong>Auto-Save:</strong> Display and column settings are automatically saved to LocalStorage</li> <li><strong>Auto-Restore:</strong> Saved settings are automatically restored when you reload the page</li> <li><strong>Persisted Settings:</strong> Column widths, visibility, pinning, font size, cell padding, page size</li> <li><strong>Reset on Reload:</strong> Filters and sort settings are reset to defaults (standard behavior)</li> <li><strong>Manual Controls:</strong> Use "Save Settings Now" to force save, or "Clear Saved Settings" to reset to defaults</li> <li><strong>Test It:</strong> Make changes, refresh the page, and see your configuration restored!</li> </ul> </div> <div class="demo-section"> <h3>Demo Controls</h3> <div class="demo-controls"> <button class="demo-btn primary" onclick="loadSampleData()">Load Sample Data</button> <button class="demo-btn" onclick="clearFilters()">Clear All Filters</button> <button class="demo-btn" onclick="addRandomData()">Add Random Data</button> <button class="demo-btn" onclick="toggleLoading()">Toggle Loading</button> <button class="demo-btn" onclick="changeTableSize()">Change Table Size</button> <button class="demo-btn" onclick="clearSettings()" style="background: #ff7875; color: white; border-color: #ff7875;">Clear Saved Settings</button> <button class="demo-btn" onclick="saveSettings()" style="background: #52c41a; color: white; border-color: #52c41a;">Save Settings Now</button> </div> </div> <div class="table-container" id="table-container"></div> </div> <script src="../src/ExceLikeTable.js"></script> <script> let table; let sampleData = []; let currentSize = 'middle'; // Generate sample data function generateSampleData(count = 100) { const names = ['John Smith', 'Jane Doe', 'Bob Johnson', 'Alice Brown', 'Charlie Davis', 'Diana Wilson', 'Eve Miller', 'Frank Garcia', 'Grace Martinez', 'Henry Anderson']; const departments = ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance', 'Operations', 'Design', 'Product']; const locations = ['New York', 'San Francisco', 'London', 'Tokyo', 'Sydney', 'Toronto', 'Berlin', 'Singapore']; const statuses = ['Active', 'Inactive', 'Pending', 'Suspended']; const data = []; for (let i = 1; i <= count; i++) { const startDate = new Date(2020, 0, 1); const endDate = new Date(2024, 11, 31); const randomDate = new Date(startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime())); data.push({ id: i, name: names[Math.floor(Math.random() * names.length)], department: departments[Math.floor(Math.random() * departments.length)], location: locations[Math.floor(Math.random() * locations.length)], salary: Math.floor(Math.random() * 150000) + 50000, experience: Math.floor(Math.random() * 20) + 1, joinDate: randomDate.toISOString().split('T')[0], status: statuses[Math.floor(Math.random() * statuses.length)], performance: Math.floor(Math.random() * 100) + 1 }); } return data; } // Column definitions const columns = [ { key: 'id', title: 'ID', dataIndex: 'id', width: 80, sortable: true, filterable: true }, { key: 'name', title: 'Name', dataIndex: 'name', width: 150, sortable: true, filterable: true }, { key: 'department', title: 'Department', dataIndex: 'department', width: 120, sortable: true, filterable: true }, { key: 'location', title: 'Location', dataIndex: 'location', width: 120, sortable: true, filterable: true }, { key: 'salary', title: 'Salary', dataIndex: 'salary', width: 120, sortable: true, filterable: true, render: (value) => `$${value.toLocaleString()}` }, { key: 'experience', title: 'Experience (Years)', dataIndex: 'experience', width: 140, sortable: true, filterable: true, render: (value) => `${value} years` }, { key: 'joinDate', title: 'Join Date', dataIndex: 'joinDate', width: 130, sortable: true, filterable: true, filterType: 'date-hierarchy' }, { key: 'status', title: 'Status', dataIndex: 'status', width: 100, sortable: true, filterable: true, render: (value) => { const colors = { 'Active': '#52c41a', 'Inactive': '#d9d9d9', 'Pending': '#faad14', 'Suspended': '#ff4d4f' }; return `<span style="color: ${colors[value] || '#000'}; font-weight: 500;">${value}</span>`; } }, { key: 'performance', title: 'Performance', dataIndex: 'performance', width: 120, sortable: true, filterable: true, render: (value) => { const color = value >= 80 ? '#52c41a' : value >= 60 ? '#faad14' : '#ff4d4f'; return `<span style="color: ${color}; font-weight: 500;">${value}%</span>`; } } ]; // Initialize table function initializeTable() { sampleData = generateSampleData(100); table = new ExceLikeTable('#table-container', { data: sampleData, columns: columns, rowKey: 'id', pagination: { pageSize: 10, showSizeChanger: true, showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} items` }, bordered: true, size: currentSize, loading: false, tableId: 'main-demo-table', persistSettings: true }); } // Demo control functions function loadSampleData() { sampleData = generateSampleData(150); table.setData(sampleData); } function clearFilters() { table.clearFilters(); } function addRandomData() { const newData = generateSampleData(50); const allData = [...sampleData, ...newData]; sampleData = allData; table.setData(allData); } function toggleLoading() { const container = document.getElementById('table-container'); const loadingOverlay = container.querySelector('.table-loading'); if (loadingOverlay) { loadingOverlay.style.display = loadingOverlay.style.display === 'none' ? 'flex' : 'none'; } } function changeTableSize() { const sizes = ['small', 'middle', 'large']; const currentIndex = sizes.indexOf(currentSize); currentSize = sizes[(currentIndex + 1) % sizes.length]; // Recreate table with new size table.destroy(); initializeTable(); } // Settings persistence functions async function clearSettings() { if (table && table.clearSettings) { const success = await table.clearSettings(); if (success) { alert('✅ Saved settings have been cleared! Refresh the page to see the default state.'); } else { alert('❌ Failed to clear settings.'); } } } async function saveSettings() { if (table && table.saveSettings) { const success = await table.saveSettings(); if (success) { alert('✅ Settings saved successfully! Your current table configuration is now persisted.'); } else { alert('❌ Failed to save settings.'); } } } // Initialize on page load document.addEventListener('DOMContentLoaded', initializeTable); </script> </body> </html>