// Hex calculator functionality export class Calculator { constructor() { this.state = { currentValue: 0, previousValue: 0, operation: null, waitingForOperand: false }; } updateDisplay() { const value = Math.max(0, Math.min(Math.floor(this.state.currentValue), Number.MAX_SAFE_INTEGER)); const hexStr = '0x' + value.toString(16).toUpperCase(); const decStr = value.toString(10); const binStr = '0b' + value.toString(2); // Update only the calculator inside the currently active tab to avoid duplicate-id issues const activeContent = document.querySelector('.tab-content.active'); if (!activeContent) { // Fallback: try to update the first calculator on the page const fallbackInput = document.querySelector('.calc-input-field'); if (fallbackInput) fallbackInput.value = hexStr; const fallbackHex = document.querySelector('.hex-value'); if (fallbackHex) fallbackHex.textContent = hexStr; const fallbackDec = document.querySelector('.dec-value'); if (fallbackDec) fallbackDec.textContent = decStr; const fallbackBin = document.querySelector('.bin-value'); if (fallbackBin) fallbackBin.textContent = binStr; return; } const input = activeContent.querySelector('.calc-input-field'); if (input) input.value = hexStr; const hexElement = activeContent.querySelector('.hex-value'); if (hexElement) hexElement.textContent = hexStr; const decElement = activeContent.querySelector('.dec-value'); if (decElement) decElement.textContent = decStr; const binElement = activeContent.querySelector('.bin-value'); if (binElement) binElement.textContent = binStr; } input(digit) { if (this.state.waitingForOperand) { this.state.currentValue = 0; this.state.waitingForOperand = false; } const digitValue = parseInt(digit, 16); if (isNaN(digitValue)) return; const newValue = this.state.currentValue * 16 + digitValue; if (newValue <= Number.MAX_SAFE_INTEGER && newValue >= 0) { this.state.currentValue = newValue; } this.updateDisplay(); } operation(operation) { // If there is a pending operation and we are not waiting for a new operand, // evaluate it first so chained operations work as expected. if (this.state.operation !== null && !this.state.waitingForOperand) { this.equals(false); } this.state.previousValue = this.state.currentValue; this.state.operation = operation; this.state.waitingForOperand = true; } equals(updateDisplay = true) { if (this.state.operation && this.state.previousValue !== null) { const prev = Math.floor(this.state.previousValue); const curr = Math.floor(this.state.currentValue); try { let result = 0; switch (this.state.operation) { case '+': result = prev + curr; break; case '-': result = prev - curr; break; case '*': result = prev * curr; break; case '/': if (curr === 0) { alert('Division durch Null!'); return; } result = Math.floor(prev / curr); break; case 'MOD': if (curr === 0) { alert('Modulo durch Null!'); return; } result = prev % curr; break; } this.state.currentValue = Math.max(0, Math.min(result, Number.MAX_SAFE_INTEGER)); } catch (error) { alert('Berechnungsfehler: ' + error.message); this.state.currentValue = 0; } this.state.operation = null; this.state.previousValue = 0; this.state.waitingForOperand = true; } if (updateDisplay) { this.updateDisplay(); } } clear() { this.state.currentValue = 0; this.state.previousValue = 0; this.state.operation = null; this.state.waitingForOperand = false; this.updateDisplay(); } backspace() { if (!this.state.waitingForOperand) { this.state.currentValue = Math.floor(this.state.currentValue / 16); this.updateDisplay(); } } setupEventListeners() { // Event delegation for calculator buttons document.addEventListener('click', (e) => { // Only handle clicks on calculator buttons if (!e.target.classList.contains('calc-btn')) return; const button = e.target; if (button.classList.contains('number')) { this.input(button.textContent); } else if (button.classList.contains('operation')) { this.operation(button.textContent); } else if (button.classList.contains('equals')) { this.equals(); } else if (button.classList.contains('clear')) { this.clear(); } else if (button.classList.contains('backspace')) { this.backspace(); } }); // Keyboard support document.addEventListener('keydown', (e) => { if (e.target.tagName === 'INPUT' && !e.target.readOnly) return; const key = e.key.toUpperCase(); if (/^[0-9A-F]$/.test(key)) { e.preventDefault(); this.input(key); } else if (key === '+') { e.preventDefault(); this.operation('+'); } else if (key === '-') { e.preventDefault(); this.operation('-'); } else if (key === '*') { e.preventDefault(); this.operation('*'); } else if (key === '/') { e.preventDefault(); this.operation('/'); } else if (key === 'ENTER' || key === '=') { e.preventDefault(); this.equals(); } else if (key === 'ESCAPE' || key === 'DELETE') { // Use Escape or Delete to clear. Do not use 'C' since it collides with hex digit C. e.preventDefault(); this.clear(); } else if (key === 'BACKSPACE') { e.preventDefault(); this.backspace(); } }); } generateHTML() { return `