Skip to content

Instantly share code, notes, and snippets.

@shijiezhou1
Last active December 18, 2024 14:07
Show Gist options
  • Save shijiezhou1/5821f3476bf9d5b7a60c92d3890846e8 to your computer and use it in GitHub Desktop.
Save shijiezhou1/5821f3476bf9d5b7a60c92d3890846e8 to your computer and use it in GitHub Desktop.
Teach you how to make a simple handsontable
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.css" />
<script src="https://cdn.jsdelivr.net/npm/handsontable/dist/handsontable.full.min.js"></script>
<style>
.htCore .yellow {
background-color: yellow;
/* Change this color as needed */
}
.htCore .new-class {
background-color: lightblue;
/* New class color */
}
</style>
</head>
<body>
<div id="example" class="handsontable-container"></div>
<button id="changeClassButton">Change Cell Class</button>
<button id="downloadCSVButton">Download CSV</button>
<div id="changesDisplay"></div>
<script>
document.addEventListener("DOMContentLoaded", function () {
const data = [
["Tesla", "Model S", "2023-01-15", 5, 2, "ORD123", "USA"],
["Volvo", "XC90", "2023-02-20", 3, 1, "ORD124", "Sweden"],
["Toyota", "Camry", "2023-03-10", 10, 4, "ORD125", "Japan"],
["Ford", "Mustang", "2023-04-05", 7, 3, "ORD126", "USA"],
["Tesla", "Model 3", "2023-05-12", 8, 2, "ORD127", "USA"],
["Volvo", "S60", "2023-06-18", 4, 1, "ORD128", "Sweden"],
["Toyota", "Corolla", "2023-07-25", 12, 5, "ORD129", "Japan"],
["Ford", "F-150", "2023-08-30", 6, 2, "ORD130", "USA"],
];
const colHeaders = [
"Company name",
"Name",
"Sell date",
"In stock",
"Qty",
"Order ID",
"Country"
]
const columns = [
{ data: 1, type: "text" },
{ data: 2, type: "text" },
{ data: 3, type: "text" },
{
data: 4,
type: "text",
},
{ data: 5, type: "text" },
{
data: 6,
type: "text",
},
{
data: 7,
type: "text",
},
]
const container = document.getElementById("example");
const changesLog = []; // Array to store changes
const hot = new Handsontable(container, {
data: data,
colHeaders: colHeaders,
columns: columns,
licenseKey: "non-commercial-and-evaluation",
afterChange: function (changes, source) {
if (source === "loadData") {
return; // Don't highlight when loading data
}
console.log(changes);
if (changes) {
// Check if there are changes
changes.forEach(([row, prop, oldValue, newValue]) => {
if (oldValue !== newValue) {
// Update the comment for the changed cell
const cell = hot.getCell(row, prop - 1); // Adjust prop for zero-based index
if (cell) {
// Retrieve the existing comment
const existingComment = hot.getCellMeta(row, prop - 1).comment?.value || '';
const commentText = `- Changed from ${oldValue} ➡️ ${newValue} on ${new Date().toLocaleString()}`;
// Append the new change to the existing comment
const newComment = existingComment ? `${commentText}\n\n${existingComment}` : commentText;
hot.setCellMeta(row, prop - 1, 'comment', { value: newComment, readOnly: true }); // Set new comment as read-only
}
// Record the change in the changesLog array
changesLog.push({ row, prop, oldValue, newValue }); // Store change details
renderChangesLog(); // Call function to render changes
}
});
}
hot.render();
},
comments: true, // Keep comments enabled
// Add these options to improve user experience
manualColumnResize: true,
manualRowResize: true,
contextMenu: ['copy', 'copy_with_column_headers'],
filters: true,
// enable the column menu
dropdownMenu: true,
copyPaste: {
copyColumnHeaders: true,
copyColumnGroupHeaders: true,
copyColumnHeadersOnly: true,
}
});
function renderChangesLog() {
const changesDisplay = document.getElementById("changesDisplay");
changesDisplay.innerHTML = ""; // Clear previous content
changesLog.forEach(change => {
const changeItem = document.createElement("div");
changeItem.textContent = `Row: ${change.row}, Column: ${change.prop}, Old Value: ${change.oldValue}, New Value: ${change.newValue}`;
// changeItem.classList.add("yellow"); // Add the yellow class to each change log item
changesDisplay.appendChild(changeItem);
});
}
document
.getElementById("changeClassButton")
.addEventListener("click", function () {
// Add yellow class to specific change log items based on changesLog
console.log(changesLog);
changesLog.forEach(change => {
const cell = hot.getCell(change.row, change.prop - 1);
if (cell) {
cell.classList.remove('highlighted'); // Remove previous highlight class if needed
cell.classList.add('new-class'); // Add new class to the cell
} else {
console.log("Cell not found.");
}
});
// Render the changesLog in the changesDisplay element
renderChangesLog(); // Call the function to display changes
});
document.getElementById("downloadCSVButton").addEventListener("click", function () {
const exportPlugin = hot.getPlugin('exportFile');
// Create a new data array with formatted dates
const formattedData = hot.getData().map(row => {
return row.map((cell, index) => {
// Check if the cell is a date (assuming the date is in the third column, index 2)
if (index === 2 && cell instanceof Date) {
return cell.toLocaleDateString(); // Format the date as a string
}
return cell; // Return the cell as is for other columns
});
});
exportPlugin.downloadFile('csv', {
bom: false,
columnDelimiter: ',',
columnHeaders: false,
exportHiddenColumns: true,
exportHiddenRows: true,
fileExtension: 'csv',
filename: 'Handsontable-CSV-file_[YYYY]-[MM]-[DD]',
mimeType: 'text/csv',
rowDelimiter: '\r\n',
rowHeaders: true,
data: formattedData
});
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment