Initial version

This commit is contained in:
2026-01-30 12:08:22 +02:00
commit db3e46de18
13 changed files with 4248 additions and 0 deletions

180
js/app.js Normal file
View File

@@ -0,0 +1,180 @@
// Main application logic
let debounceTimer = null;
const EXAMPLE_CODE = 'DC2.Dw Gm L W T+ Phvwalt Sk? Cbk--^\\bl+lum B- A+ N? M+++!1 O/ H+++ $ F+o R++ Ac+++! J++ S U- I-- V- Q--- Tc+++[SE] E++';
// DOM elements
const input = document.getElementById('dragon-code-input');
const welcomeMessage = document.getElementById('welcome-message');
const decodedOutput = document.getElementById('decoded-output');
const loadExampleBtn = document.getElementById('load-example');
const clearInputBtn = document.getElementById('clear-input');
// Category sections
const sections = {
species: document.getElementById('species-content'),
physical: document.getElementById('physical-content'),
appearance: document.getElementById('appearance-content'),
abilities: document.getElementById('abilities-content'),
life: document.getElementById('life-content'),
personality: document.getElementById('personality-content'),
other: document.getElementById('other-content'),
errors: document.getElementById('errors-content')
};
// Event listeners
input.addEventListener('input', handleInput);
loadExampleBtn.addEventListener('click', loadExample);
clearInputBtn.addEventListener('click', clearInput);
function handleInput() {
// Debounce input to avoid excessive processing
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
const code = input.value.trim();
if (code) {
processCode(code);
} else {
showWelcome();
}
}, 500);
}
function loadExample() {
input.value = EXAMPLE_CODE;
processCode(EXAMPLE_CODE);
}
function clearInput() {
input.value = '';
showWelcome();
}
function showWelcome() {
welcomeMessage.classList.remove('hidden');
decodedOutput.classList.add('hidden');
}
function processCode(code) {
try {
// Parse the Dragon Code
const parsed = parseDragonCode(code);
// Decode to human-readable format
const decoded = decodeDragonCode(parsed);
// Render the results
renderResults(decoded, parsed.errors);
} catch (error) {
console.error('Error processing code:', error);
showError('An unexpected error occurred while processing the code.');
}
}
function renderResults(decoded, errors) {
// Clear all sections
Object.values(sections).forEach(section => {
section.innerHTML = '';
});
// Hide welcome, show output
welcomeMessage.classList.add('hidden');
decodedOutput.classList.remove('hidden');
// Render each category
renderCategory('species', decoded.species);
renderCategory('physical', decoded.physical);
renderCategory('appearance', decoded.appearance);
renderCategory('abilities', decoded.abilities);
renderCategory('life', decoded.life);
renderCategory('personality', decoded.personality);
renderCategory('other', decoded.other);
// Render errors if any
if (errors && errors.length > 0) {
document.getElementById('errors-section').classList.remove('hidden');
errors.forEach(error => {
const errorElement = createTraitItem('Warning', error, '', 'warning');
sections.errors.appendChild(errorElement);
});
} else {
document.getElementById('errors-section').classList.add('hidden');
}
// Hide empty sections
hideEmptySections();
}
function renderCategory(categoryName, items) {
if (!items || items.length === 0) return;
const section = sections[categoryName];
items.forEach(item => {
const element = createTraitItem(item.label, item.value, item.tag, item.type || 'normal');
section.appendChild(element);
});
}
function createTraitItem(label, value, tag, type = 'normal') {
const div = document.createElement('div');
div.className = `trait-item ${type}`;
const labelDiv = document.createElement('div');
labelDiv.className = 'trait-label';
labelDiv.textContent = label;
const valueDiv = document.createElement('div');
valueDiv.className = 'trait-value';
valueDiv.textContent = value;
div.appendChild(labelDiv);
div.appendChild(valueDiv);
if (tag) {
const tagSpan = document.createElement('span');
tagSpan.className = 'trait-tag';
tagSpan.textContent = tag;
div.appendChild(tagSpan);
}
return div;
}
function hideEmptySections() {
const sectionElements = {
species: document.getElementById('species-section'),
physical: document.getElementById('physical-section'),
appearance: document.getElementById('appearance-section'),
abilities: document.getElementById('abilities-section'),
life: document.getElementById('life-section'),
personality: document.getElementById('personality-section'),
other: document.getElementById('other-section')
};
Object.keys(sectionElements).forEach(key => {
const content = sections[key];
const section = sectionElements[key];
if (content.children.length === 0) {
section.classList.add('hidden');
} else {
section.classList.remove('hidden');
}
});
}
function showError(message) {
welcomeMessage.classList.add('hidden');
decodedOutput.classList.remove('hidden');
Object.values(sections).forEach(section => {
section.innerHTML = '';
});
document.getElementById('errors-section').classList.remove('hidden');
const errorElement = createTraitItem('Error', message, '', 'error');
sections.errors.appendChild(errorElement);
hideEmptySections();
}