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!

353 lines (323 loc) 11 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 - Advanced Example</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: 1000px; 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; } .table-container { height: 500px; border: 1px solid #d9d9d9; border-radius: 4px; } .progress-bar { width: 100%; height: 16px; background: #f0f0f0; border-radius: 8px; overflow: hidden; position: relative; } .progress-fill { height: 100%; background: linear-gradient(90deg, #52c41a 0%, #faad14 50%, #ff4d4f 100%); transition: width 0.3s ease; } .progress-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 12px; font-weight: 500; color: #333; } .status-badge { padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: 500; display: inline-block; } .status-active { background: #f6ffed; color: #52c41a; border: 1px solid #b7eb8f; } .status-inactive { background: #f5f5f5; color: #8c8c8c; border: 1px solid #d9d9d9; } .status-pending { background: #fffbe6; color: #faad14; border: 1px solid #ffe58f; } .status-suspended { background: #fff2f0; color: #ff4d4f; border: 1px solid #ffb3b3; } .demo-controls { margin-bottom: 16px; display: flex; gap: 8px; flex-wrap: wrap; } .demo-btn { padding: 6px 12px; border: 1px solid #d9d9d9; background: white; border-radius: 4px; cursor: pointer; font-size: 12px; transition: all 0.2s; } .demo-btn:hover { border-color: #1890ff; color: #1890ff; } .feature-info { background: #e6f7ff; padding: 12px; border-radius: 4px; margin-bottom: 16px; border: 1px solid #91d5ff; } .feature-info h3 { margin: 0 0 8px 0; color: #1890ff; } .feature-info ul { margin: 0; padding-left: 20px; font-size: 14px; } </style> </head> <body> <div class="container"> <h1>⚡ VanillaJS ExceLike Table - Advanced Features</h1> <div class="feature-info"> <h3>Advanced Features Demonstrated:</h3> <ul> <li><strong>Custom Renderers:</strong> Progress bars, status badges, formatted numbers</li> <li><strong>Range Filters:</strong> Numeric columns with slider controls</li> <li><strong>Date Hierarchy:</strong> Expandable year/month filtering</li> <li><strong>Custom Sorters:</strong> Complex sorting logic for formatted data</li> <li><strong>Dynamic Updates:</strong> Real-time data modification</li> </ul> </div> <div class="demo-controls"> <button class="demo-btn" onclick="updateProgress()">Update Progress</button> <button class="demo-btn" onclick="changeStatuses()">Change Statuses</button> <button class="demo-btn" onclick="addNewEmployee()">Add Employee</button> <button class="demo-btn" onclick="refreshData()">Refresh Data</button> </div> <div class="table-container" id="table-container"></div> </div> <script src="../src/ExceLikeTable.js"></script> <script> let table; let employeeData = []; // Generate advanced sample data function generateAdvancedData() { const names = ['John Smith', 'Jane Doe', 'Bob Johnson', 'Alice Brown', 'Charlie Davis', 'Diana Wilson', 'Eve Miller', 'Frank Garcia', 'Grace Martinez', 'Henry Anderson', 'Ivy Chen', 'Jack Wilson', 'Kate Roberts', 'Liam Taylor', 'Mia Johnson']; const departments = ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance', 'Operations', 'Design', 'Product', 'Support', 'Research']; const locations = ['New York', 'San Francisco', 'London', 'Tokyo', 'Sydney', 'Toronto', 'Berlin', 'Singapore', 'Mumbai', 'Dubai']; const statuses = ['Active', 'Inactive', 'Pending', 'Suspended']; const skills = ['JavaScript', 'React', 'Node.js', 'Python', 'Java', 'C++', 'SQL', 'MongoDB', 'AWS', 'Docker']; const data = []; for (let i = 1; i <= 30; 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, projectsCompleted: Math.floor(Math.random() * 50) + 1, skills: skills.slice(0, Math.floor(Math.random() * 5) + 2).join(', '), rating: (Math.random() * 4 + 1).toFixed(1) }); } return data; } // Advanced column definitions with custom renderers const advancedColumns = [ { key: 'id', title: 'ID', dataIndex: 'id', width: 80, sortable: true, filterable: true }, { key: 'name', title: 'Employee Name', dataIndex: 'name', width: 150, sortable: true, filterable: true, render: (value, record) => { return `<strong>${value}</strong><br><small style="color: #999;">${record.department}</small>`; } }, { 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', dataIndex: 'experience', width: 100, sortable: true, filterable: true, render: (value) => `${value} yrs` }, { 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 className = `status-${value.toLowerCase()}`; return `<span class="status-badge ${className}">${value}</span>`; } }, { key: 'performance', title: 'Performance', dataIndex: 'performance', width: 120, sortable: true, filterable: true, render: (value) => { return ` <div class="progress-bar"> <div class="progress-fill" style="width: ${value}%"></div> <div class="progress-text">${value}%</div> </div> `; } }, { key: 'projectsCompleted', title: 'Projects', dataIndex: 'projectsCompleted', width: 100, sortable: true, filterable: true, render: (value) => `<span style="color: #1890ff; font-weight: 500;">${value}</span>` }, { key: 'rating', title: 'Rating', dataIndex: 'rating', width: 100, sortable: true, filterable: true, render: (value) => { const stars = '★'.repeat(Math.floor(value)) + '☆'.repeat(5 - Math.floor(value)); return `<span style="color: #faad14;">${stars}</span><br><small>${value}/5</small>`; } } ]; // Demo control functions function updateProgress() { employeeData = employeeData.map(emp => ({ ...emp, performance: Math.floor(Math.random() * 100) + 1 })); table.setData(employeeData); } function changeStatuses() { const statuses = ['Active', 'Inactive', 'Pending', 'Suspended']; employeeData = employeeData.map(emp => ({ ...emp, status: statuses[Math.floor(Math.random() * statuses.length)] })); table.setData(employeeData); } function addNewEmployee() { const newId = Math.max(...employeeData.map(e => e.id)) + 1; const names = ['Alex Johnson', 'Sam Wilson', 'Taylor Brown', 'Jordan Davis', 'Casey Miller']; const departments = ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance']; const newEmployee = { id: newId, name: names[Math.floor(Math.random() * names.length)], department: departments[Math.floor(Math.random() * departments.length)], location: 'New York', salary: Math.floor(Math.random() * 100000) + 60000, experience: Math.floor(Math.random() * 10) + 1, joinDate: new Date().toISOString().split('T')[0], status: 'Active', performance: Math.floor(Math.random() * 100) + 1, projectsCompleted: Math.floor(Math.random() * 20) + 1, skills: 'JavaScript, React, Node.js', rating: (Math.random() * 4 + 1).toFixed(1) }; employeeData.push(newEmployee); table.setData(employeeData); } function refreshData() { employeeData = generateAdvancedData(); table.setData(employeeData); } // Initialize advanced table document.addEventListener('DOMContentLoaded', () => { employeeData = generateAdvancedData(); table = new ExceLikeTable('#table-container', { data: employeeData, columns: advancedColumns, rowKey: 'id', pagination: { pageSize: 8, showSizeChanger: true, showTotal: (total, range) => `Showing ${range[0]}-${range[1]} of ${total} employees` }, bordered: true, size: 'middle', loading: false }); }); </script> </body> </html>