Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f78444b

Browse files
Add files via upload
1 parent c2f3ce5 commit f78444b

File tree

13 files changed

+809
-0
lines changed

13 files changed

+809
-0
lines changed
864 KB
Loading[フレーム]
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Class definition for an editable table
2+
class EditableTable {
3+
// Constructor to set up an editable table with the specified number of rows and columns
4+
constructor(numRows, numCols) {
5+
this.numRows = numRows; // Store the number of rows
6+
this.numCols = numCols; // Store the number of columns
7+
this.tableElement = document.getElementById('table'); // Find the table HTML element by ID
8+
this.cells = []; // Array to keep track of individual cell elements
9+
this.currentCellIndex = 0; // Index of the currently active cell
10+
this.previousCellIndex = null; // Index of the previously active cell, for navigation purposes
11+
this.initializeTable(); // Call method to create the table cells
12+
this.addEventListeners(); // Call method to attach necessary event listeners
13+
}
14+
15+
// Method to create table cells and attach them to the table
16+
initializeTable() {
17+
for (let i = 0; i < this.numRows; i++) { // Iterate through the number of rows
18+
const rowElement = document.createElement('tr'); // Create a new table row (tr) element
19+
for (let j = 0; j < this.numCols; j++) { // Iterate through the number of columns
20+
const cellElement = document.createElement('td'); // Create a new table cell (td) element
21+
cellElement.textContent = `Cell ${i * this.numCols + j + 1}`; // Set the text content of the cell
22+
rowElement.appendChild(cellElement); // Append the cell to the current row
23+
this.cells.push(cellElement); // Add the cell element to the array of all cells
24+
25+
// Add a click event listener to each cell
26+
cellElement.addEventListener('click', (e) => {
27+
if (cellElement.getAttribute('contenteditable') === 'true') { // If the cell is already editable, do nothing
28+
return;
29+
}
30+
31+
// Find any cell that is currently editable
32+
const editableCell = this.cells.find(cell => cell.getAttribute('contenteditable') === 'true');
33+
34+
if (editableCell) { // If there is an editable cell
35+
editableCell.removeAttribute('contenteditable'); // Remove its contenteditable attribute
36+
editableCell.classList.remove('editable'); // Remove the 'editable' class
37+
}
38+
39+
// Update the current cell index to this cell
40+
this.currentCellIndex = this.cells.indexOf(cellElement);
41+
42+
// Remove the 'active' class from all cells
43+
this.cells.forEach(cell => cell.classList.remove('active'));
44+
45+
// Add the 'active' class to the currently clicked cell
46+
cellElement.classList.add('active');
47+
});
48+
49+
// Add a double click event listener to make the cell editable
50+
cellElement.addEventListener('dblclick', (e) => {
51+
if (cellElement.getAttribute('contenteditable') === 'true') { // If the cell is already editable, do nothing
52+
return;
53+
}
54+
55+
this.makeCellEditable(cellElement); // Call the makeCellEditable method
56+
});
57+
}
58+
// Append the row to the table element
59+
this.tableElement.appendChild(rowElement);
60+
}
61+
// Set the initially active cell with the 'active' class
62+
this.cells[this.currentCellIndex].classList.add('active');
63+
}
64+
65+
// Method to add the keydown event listener to the document for navigation and editing
66+
addEventListeners() {
67+
// Listen for the keydown event on the entire document
68+
document.addEventListener('keydown', (e) => {
69+
// Get the current active cell
70+
const currentCell = this.cells[this.currentCellIndex];
71+
// If the current cell is not in an editable state
72+
if (!currentCell.classList.contains('editable')) {
73+
// Handle arrow keys and Enter for navigation and editing
74+
switch (e.key) {
75+
case 'ArrowUp': this.handleNavigation('up'); break; // Handle up arrow navigation
76+
case 'ArrowDown': this.handleNavigation('down'); break; // Handle down arrow navigation
77+
case 'ArrowLeft': this.handleNavigation('left'); break; // Handle left arrow navigation
78+
case 'ArrowRight': this.handleNavigation('right'); break; // Handle right arrow navigation
79+
case 'Enter': if (this.previousCellIndex !== null) // If Enter is pressed and there is a previous cell
80+
this.cells[this.previousCellIndex].classList.remove('active'); // Remove active class from previous cell
81+
e.preventDefault(); // Prevent default Enter key action
82+
this.makeCellEditable(currentCell); // Make current cell editable
83+
this.previousCellIndex = this.currentCellIndex; // Set the current cell as the previous cell for next iteration
84+
break;
85+
}
86+
} else if (e.key === 'Enter') { // If the current cell is editable and Enter is pressed
87+
this.exitCellEditingMode(currentCell); // Exit editing mode for the cell
88+
}
89+
});
90+
}
91+
92+
// Method to make a specific cell editable
93+
makeCellEditable(cell) {
94+
if (!cell.classList.contains('editable')) { // If the cell is not already editable
95+
const tempCellData = cell.textContent; // Store the current text content of the cell
96+
localStorage.setItem('tempCellData', tempCellData); // Save the content in local storage in case we need to revert changes
97+
cell.classList.add('editable'); // Add 'editable' class to the cell
98+
cell.contentEditable = 'true'; // Make the cell content editable
99+
cell.focus(); // Focus on the cell to start editing
100+
this.selectTextInsideCell(cell); // Select the text inside the cell for user convenience
101+
this.addEscapeKeyListener(cell); // Add key listener for 'Escape' key to cancel editing
102+
}
103+
}
104+
105+
// Method to exit editing mode for a cell
106+
exitCellEditingMode(cell) {
107+
cell.contentEditable = 'false'; // Set content of the cell to be not editable
108+
cell.classList.remove('editable'); // Remove 'editable' class from cell
109+
cell.classList.add('active'); // Re-add 'active' class to cell
110+
this.clearTextSelection(); // Clear any text selection in the document
111+
localStorage.removeItem('tempCellData'); // Remove stored cell data from local storage
112+
}
113+
114+
// Method to restore original cell content on 'Escape' key press
115+
addEscapeKeyListener(cell) {
116+
// Listen for keydown event on the cell
117+
cell.addEventListener('keydown', (e) => {
118+
if (e.key === 'Escape') { // If Escape key is pressed
119+
const restoredData = localStorage.getItem('tempCellData'); // Retrieve the original content from local storage
120+
121+
if (restoredData && restoredData !== '') { // If there was original content
122+
cell.textContent = restoredData; // Set the cell content back to the original
123+
} else if (restoredData === '') { // If the original content was empty
124+
cell.textContent = ''; // Leave the cell content empty
125+
}
126+
127+
this.exitCellEditingMode(cell); // Exit editing mode
128+
}
129+
});
130+
}
131+
132+
// Method to select text within a cell for editing
133+
selectTextInsideCell(cell) {
134+
const textRange = document.createRange(); // Create a new text range
135+
textRange.selectNodeContents(cell); // Select the contents of the cell
136+
window.getSelection().removeAllRanges(); // Remove all existing selections
137+
window.getSelection().addRange(textRange); // Add the new range to the selection
138+
}
139+
140+
// Method to clear any text selection in the document
141+
clearTextSelection() {
142+
window.getSelection().removeAllRanges(); // Remove all selections from the document
143+
}
144+
145+
// Method to handle cell navigation using arrow keys
146+
handleNavigation(direction) {
147+
this.cells[this.currentCellIndex].classList.remove('active'); // Remove the 'active' class from the currently active cell
148+
// Which direction to navigate
149+
switch (direction) {
150+
case 'up': // Up arrow key was pressed
151+
if (this.currentCellIndex >= this.numCols) // Prevent navigating beyond the first row
152+
this.currentCellIndex -= this.numCols; // Move up one row
153+
break;
154+
case 'down': // Down arrow key was pressed
155+
if (this.currentCellIndex < this.cells.length - this.numCols) // Prevent navigating beyond the last row
156+
this.currentCellIndex += this.numCols; // Move down one row
157+
break;
158+
case 'left': // Left arrow key was pressed
159+
if (this.currentCellIndex % this.numCols !== 0) // Prevent navigating beyond the first column
160+
this.currentCellIndex--; // Move left one column
161+
break;
162+
case 'right': // Right arrow key was pressed
163+
if (this.currentCellIndex % this.numCols !== this.numCols - 1 && // Prevent navigating beyond the last column
164+
this.currentCellIndex < this.cells.length - 1) // Prevent navigating beyond the last cell
165+
this.currentCellIndex++; // Move right one column
166+
break;
167+
}
168+
this.cells[this.currentCellIndex].classList.add('active'); // Add 'active' class to the new current cell
169+
}
170+
}
171+
172+
// Listen for the 'DOMContentLoaded' event on the document, which fires when the DOM is fully loaded and parsed
173+
document.addEventListener('DOMContentLoaded', function () {
174+
// Set a timeout of 500 milliseconds to delay the execution of the following function
175+
setTimeout(function () {
176+
// Prompt the user to enter the number of rows and parse it as an integer
177+
const numRows = parseInt(prompt('Enter the number of rows:'));
178+
// Prompt the user to enter the number of columns and parse it as an integer
179+
const numCols = parseInt(prompt('Enter the number of columns:'));
180+
181+
// Create a new instance of EditableTable with the user-provided number of rows and columns
182+
const editableTable = new EditableTable(numRows, numCols);
183+
}, 500); // The delay time in milliseconds before the function is executed after the event fires
184+
});

‎source-code/Dynamic-Table/index.html‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<title>HTML Editable Table with Mouse and Keyboard Arrow Keys Navigation</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
9+
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu">
10+
<link rel="stylesheet" href="style.css">
11+
</head>
12+
13+
<body>
14+
<table id="table"></table>
15+
<script src="cell-editor.js"></script>
16+
</body>
17+
18+
</html>

‎source-code/Dynamic-Table/style.css‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
body {
2+
font-family: "Ubuntu";
3+
margin: 0;
4+
padding: 0;
5+
background-image: url("../gilgeekify-army.jpg");
6+
background-size: cover;
7+
background-position: center;
8+
background-attachment: fixed;
9+
height: 100vh;
10+
display: flex;
11+
justify-content: center;
12+
align-items: center;
13+
font-size: 30px;
14+
font-weight: 900;
15+
}
16+
17+
table {
18+
border-collapse: collapse;
19+
margin: 0 auto;
20+
background-color: #ffffff80;
21+
}
22+
23+
td {
24+
border: 1px solid #000;
25+
padding: 10px;
26+
text-align: center;
27+
transition: 200ms;
28+
}
29+
30+
td.active {
31+
background-color: #0f0;
32+
}
33+
34+
td.editable {
35+
background-color: #ff0;
36+
}
37+
38+
td.editable:focus {
39+
transform: scale(1.1);
40+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /