技术需求:开发支持行列增删及右键操作的动态HTML表格
Hey there! I've built a complete dynamic table implementation that meets all your requirements. It's straightforward to use, with a clean right-click menu and intuitive controls. Let's take a look at how it works.
Dynamic Editable Table (Insert/Delete Rows & Columns)
Core Features
- Create a table by specifying the number of rows and columns
- Right-click any cell to access options to insert/delete the corresponding row or column
- Add new rows/columns to an existing table with dedicated buttons
Full Implementation Code
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Dynamic Table</title> <link rel="stylesheet" href="styles.css"> </head> <body> <div class="container"> <div class="table-controls"> <label for="rowCount">Rows:</label> <input type="number" id="rowCount" min="1" value="3"> <label for="colCount">Columns:</label> <input type="number" id="colCount" min="1" value="3"> <button id="createTable">Create Table</button> </div> <div id="tableContainer"></div> <div class="additional-controls"> <button id="addRow">Add Row</button> <button id="addColumn">Add Column</button> </div> <!-- Right-click menu --> <div id="contextMenu" class="context-menu"> <div class="menu-item" data-action="insertRowAbove">Insert Row Above</div> <div class="menu-item" data-action="insertRowBelow">Insert Row Below</div> <div class="menu-item" data-action="deleteRow">Delete Row</div> <div class="menu-separator"></div> <div class="menu-item" data-action="insertColumnLeft">Insert Column Left</div> <div class="menu-item" data-action="insertColumnRight">Insert Column Right</div> <div class="menu-item" data-action="deleteColumn">Delete Column</div> </div> </div> <script src="script.js"></script> </body> </html>
CSS
.container { max-width: 800px; margin: 2rem auto; padding: 0 1rem; } .table-controls { margin-bottom: 1.5rem; display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; } .table-controls input { padding: 0.5rem; width: 80px; } .table-controls button, .additional-controls button { padding: 0.5rem 1rem; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } .table-controls button:hover, .additional-controls button:hover { background: #0056b3; } #tableContainer { margin: 1.5rem 0; overflow-x: auto; } table { border-collapse: collapse; width: 100%; min-width: 400px; } th, td { border: 1px solid #dee2e6; padding: 0.75rem; text-align: center; position: relative; } th { background-color: #f8f9fa; font-weight: bold; } .additional-controls { margin-top: 1.5rem; display: flex; gap: 1rem; } /* Context Menu Styles */ .context-menu { position: fixed; background: white; border: 1px solid #ccc; border-radius: 4px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); z-index: 1000; display: none; } .menu-item { padding: 0.5rem 1rem; cursor: pointer; } .menu-item:hover { background-color: #f8f9fa; } .menu-separator { height: 1px; background-color: #eee; margin: 0.25rem 0; }
JavaScript
// Get elements const rowCountInput = document.getElementById('rowCount'); const colCountInput = document.getElementById('colCount'); const createTableBtn = document.getElementById('createTable'); const tableContainer = document.getElementById('tableContainer'); const addRowBtn = document.getElementById('addRow'); const addColumnBtn = document.getElementById('addColumn'); const contextMenu = document.getElementById('contextMenu'); let currentTable = null; let activeCell = null; // Create table function function createTable(rows, cols) { // Clear existing table tableContainer.innerHTML = ''; const table = document.createElement('table'); const thead = document.createElement('thead'); const tbody = document.createElement('tbody'); // Create header row const headerRow = document.createElement('tr'); for (let i = 0; i < cols; i++) { const th = document.createElement('th'); th.textContent = `Column ${i + 1}`; headerRow.appendChild(th); } thead.appendChild(headerRow); table.appendChild(thead); // Create body rows for (let i = 0; i < rows; i++) { const row = document.createElement('tr'); for (let j = 0; j < cols; j++) { const td = document.createElement('td'); td.textContent = `Row ${i + 1}, Col ${j + 1}`; // Add right-click event to cells td.addEventListener('contextmenu', handleContextMenu); row.appendChild(td); } tbody.appendChild(row); } table.appendChild(tbody); tableContainer.appendChild(table); currentTable = table; } // Handle right-click menu function handleContextMenu(e) { e.preventDefault(); activeCell = e.target; // Position the menu contextMenu.style.left = `${e.pageX}px`; contextMenu.style.top = `${e.pageY}px`; contextMenu.style.display = 'block'; // Close menu when clicking elsewhere document.addEventListener('click', closeContextMenu); } function closeContextMenu() { contextMenu.style.display = 'none'; document.removeEventListener('click', closeContextMenu); } // Menu item click handlers contextMenu.querySelectorAll('.menu-item').forEach(item => { item.addEventListener('click', (e) => { const action = e.target.dataset.action; switch(action) { case 'insertRowAbove': insertRow(activeCell.parentElement, 'above'); break; case 'insertRowBelow': insertRow(activeCell.parentElement, 'below'); break; case 'deleteRow': deleteRow(activeCell.parentElement); break; case 'insertColumnLeft': insertColumn(activeCell.cellIndex, 'left'); break; case 'insertColumnRight': insertColumn(activeCell.cellIndex, 'right'); break; case 'deleteColumn': deleteColumn(activeCell.cellIndex); break; } closeContextMenu(); }); }); // Insert row function function insertRow(targetRow, position) { const newRow = document.createElement('tr'); const colCount = currentTable.querySelector('tr').children.length; for (let i = 0; i < colCount; i++) { const td = document.createElement('td'); td.textContent = `New Row, Col ${i + 1}`; td.addEventListener('contextmenu', handleContextMenu); newRow.appendChild(td); } if (position === 'above') { targetRow.parentNode.insertBefore(newRow, targetRow); } else { targetRow.parentNode.insertBefore(newRow, targetRow.nextSibling); } } // Delete row function function deleteRow(targetRow) { // Don't delete if it's the last row if (currentTable.querySelectorAll('tbody tr').length <= 1) { alert('Cannot delete the last row!'); return; } targetRow.remove(); } // Insert column function function insertColumn(colIndex, position) { // Insert in header const headerRow = currentTable.querySelector('thead tr'); const newHeader = document.createElement('th'); newHeader.textContent = `New Column`; const targetHeader = headerRow.children[colIndex]; if (position === 'left') { headerRow.insertBefore(newHeader, targetHeader); } else { headerRow.insertBefore(newHeader, targetHeader.nextSibling); } // Insert in body rows const bodyRows = currentTable.querySelectorAll('tbody tr'); bodyRows.forEach(row => { const newCell = document.createElement('td'); newCell.textContent = `${row.querySelector('td').textContent.split(',')[0]}, New Col`; newCell.addEventListener('contextmenu', handleContextMenu); const targetCell = row.children[colIndex]; if (position === 'left') { row.insertBefore(newCell, targetCell); } else { row.insertBefore(newCell, targetCell.nextSibling); } }); } // Delete column function function deleteColumn(colIndex) { // Don't delete if it's the last column if (currentTable.querySelector('tr').children.length <= 1) { alert('Cannot delete the last column!'); return; } // Delete from header currentTable.querySelector('thead tr').children[colIndex].remove(); // Delete from body rows const bodyRows = currentTable.querySelectorAll('tbody tr'); bodyRows.forEach(row => { row.children[colIndex].remove(); }); } // Add row button handler addRowBtn.addEventListener('click', () => { if (!currentTable) { alert('Please create a table first!'); return; } const lastRow = currentTable.querySelector('tbody tr:last-child'); insertRow(lastRow, 'below'); }); // Add column button handler addColumnBtn.addEventListener('click', () => { if (!currentTable) { alert('Please create a table first!'); return; } const lastColIndex = currentTable.querySelector('tr').children.length - 1; insertColumn(lastColIndex, 'right'); }); // Create table button handler createTableBtn.addEventListener('click', () => { const rows = parseInt(rowCountInput.value); const cols = parseInt(colCountInput.value); if (rows > 0 && cols > 0) { createTable(rows, cols); } else { alert('Please enter valid row and column numbers (at least 1)!'); } }); // Initialize with default table createTable(3, 3);
How to Use
- Create a Table: Enter the number of rows and columns you want, then click "Create Table". A default 3x3 table loads on page load too.
- Right-Cell Actions: Right-click any cell to open the context menu. You can insert rows above/below, delete the current row, insert columns left/right, or delete the current column.
- Quick Add Controls: Use the "Add Row" and "Add Column" buttons at the bottom to quickly append a new row to the end or a new column to the right of the existing table.
Notes
- You can't delete the last row or column (to avoid an empty table).
- The context menu closes automatically when you click anywhere else on the page.
- All new cells have the right-click functionality enabled too.
内容的提问来源于stack exchange,提问作者Harsha
相关产品推荐
相关产品推荐

