Excel-Dictionary / index_live.html
abdelhaqueidali's picture
Rename index.html to index_live.html
cc699e6 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dictionary</title>
<style>
body {
font-family: sans-serif;
margin: 20px;
background-color: #f4f4f4;
}
#container {
width: 80%;
margin: 0 auto;
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
input[type="file"], input[type="text"] { /* Keep file inputs for flexibility */
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ddd;
border-radius: 4px;
width: calc(100% - 22px);
}
#search {
margin-top: 20px;
width: 98%;
}
#results {
list-style: none;
padding: 0;
margin: 0;
}
#results li {
padding: 15px;
border-bottom: 1px solid #eee;
margin-bottom: 5px;
background-color: #fafafa;
border-radius: 4px;
}
#results li:last-child {
border-bottom: none;
}
.word-cell {
font-weight: bold;
font-size: 1.1em;
margin-bottom: 5px;
}
.translation-cell {
font-style: italic;
color: #333;
margin-bottom: 5px;
}
.additional-cell {
color: #555;
margin-bottom: 3px;
}
.hidden {
display: none;
}
.error-message {
color: red;
margin-top: 5px;
}
</style>
</head>
<body>
<div id="container">
<h2>Dictionary</h2>
<!-- File inputs are kept but hidden -->
<input type="file" id="excelFile" accept=".xlsx, .xls, .csv" style="display: none;">
<input type="file" id="mappingFile" accept=".txt" style="display: none;">
<input type="text" id="search" placeholder="Search...">
<div id="errorMessageContainer" class="error-message"></div>
<ul id="results"></ul>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
const excelFileInput = document.getElementById('excelFile');
const mappingFileInput = document.getElementById('mappingFile');
const searchInput = document.getElementById('search');
const resultsList = document.getElementById('results');
const errorMessageContainer = document.getElementById('errorMessageContainer');
let excelData = [];
let mapping = {};
// --- Helper Functions ---
// Generic function to fetch and process a file
async function fetchAndProcessFile(filename, fileType, processFunction) {
try {
const response = await fetch(filename);
if (!response.ok) {
if (response.status === 404){ //only display if file not found.
throw new Error(`${fileType} file not found: ${filename}`);
}
throw new Error(`HTTP error! status: ${response.status} for ${filename}`);
}
const data = (fileType === 'Excel') ? await response.arrayBuffer() : await response.text();
processFunction(data);
} catch (error) {
console.error(`Error loading or processing ${fileType} file:`, error);
errorMessageContainer.textContent = error.message; // Display the error
}
}
// Process Excel file
function processExcel(data) {
const workbook = XLSX.read(data, { type: 'array', raw: false });
const sheetName = workbook.SheetNames[0];
excelData = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], { header: 1, raw: false });
if (Object.keys(mapping).length > 0) { //Only display if it's loaded.
displayData(); // Initial display after both files are loaded
}
}
// Process mapping file
function processMapping(text) {
parseMapping(text);
if (excelData.length > 0){ // display if loaded.
displayData();
}
}
function parseMapping(text) {
mapping = {}; // Reset mapping
const lines = text.trim().split('\n');
lines.forEach(line => {
const [column, fieldName] = line.trim().split('|');
if (column && fieldName) {
mapping[column.trim()] = fieldName.trim();
}
});
//console.log("Parsed Mapping:", mapping);
}
function displayData(filteredData = null) {
resultsList.innerHTML = ''; // Clear previous results
errorMessageContainer.textContent = ''; // Clear previous error messages
const dataToDisplay = filteredData || excelData;
dataToDisplay.forEach(row => {
if (row.length === 0) return; // Skip empty rows
const listItem = document.createElement('li');
let hasContent = false;
// Check and add word cell
if (mapping['A'] ) { // Always map 'A' if it exists in the mapping
const colIndexA = 'A'.charCodeAt(0) - 'A'.charCodeAt(0);
if (row[colIndexA] != undefined){ //Check the column if it's empty
const wordCell = document.createElement('div');
wordCell.className = 'word-cell';
wordCell.textContent = row[colIndexA];
listItem.appendChild(wordCell);
hasContent = true;
}
}
//Check and add B cell
if (mapping['B']) {
const colIndexB = 'B'.charCodeAt(0) - 'A'.charCodeAt(0);
if (row[colIndexB] != undefined){
const translationCell = document.createElement('div');
translationCell.className = 'translation-cell';
translationCell.textContent = row[colIndexB];
listItem.appendChild(translationCell);
hasContent = true;
}
}
// Check and add additional cells (C onwards)
for (let i = 2; i < 26; i++) { // Iterate from C (index 2) up to Z
const columnLetter = String.fromCharCode('A'.charCodeAt(0) + i);
if (mapping[columnLetter]) {
const colIndex = columnLetter.charCodeAt(0) - 'A'.charCodeAt(0);
if(row[colIndex] != undefined) { // Check if the cell is empty
const additionalCell = document.createElement('div');
additionalCell.className = 'additional-cell';
additionalCell.textContent = `${mapping[columnLetter]}: ${row[colIndex]}`;
listItem.appendChild(additionalCell);
hasContent = true;
}
}
}
if (hasContent) {
resultsList.appendChild(listItem);
}
});
}
// --- Event Listeners ---
searchInput.addEventListener('input', () => {
const searchTerm = searchInput.value.toLowerCase().trim();
if (!searchTerm) {
displayData(); //Display All data.
return;
}
const filteredData = excelData.filter(row => {
return row.some(cell => {
if (typeof cell === 'string') {
return cell.toLowerCase().includes(searchTerm);
} else if (typeof cell === 'number') {
return cell.toString().toLowerCase().includes(searchTerm);
}
return false;
});
});
displayData(filteredData);
});
// --- Initial Load ---
// Attempt to load both files automatically on page load
fetchAndProcessFile('mapping.txt', 'Mapping', processMapping);
// Try loading with different extensions
const excelExtensions = ['.xlsx', '.xls', '.csv'];
let excelLoaded = false;
async function loadExcelWithDifferentExtensions() {
for (const ext of excelExtensions) {
if (excelLoaded) break; // Exit if already loaded
try {
await fetchAndProcessFile(`dictionary${ext}`, 'Excel', (data) => {
processExcel(data);
excelLoaded = true; // Set the flag once successfully loaded
});
}
catch (error)
{
// console.error to avoid double errors.
console.error(`dictionary${ext} did not load. `);
}
}
if (!excelLoaded)
{
// if no files found display error.
errorMessageContainer.textContent = "No Excel file found (dictionary.xlsx, dictionary.xls, or dictionary.csv)";
}
}
loadExcelWithDifferentExtensions();
</script>
</body>
</html>