// Enhanced UX utilities for hex editor companion workflow import { copyToClipboard as originalCopyToClipboard, formatHex } from './utils.js'; // ============================================ // 1. KEYBOARD SHORTCUTS // ============================================ export function setupKeyboardShortcuts() { document.addEventListener('keydown', (e) => { // Ctrl+1-9: Switch tabs if (e.ctrlKey && !e.shiftKey && !e.altKey) { const num = parseInt(e.key); if (num >= 1 && num <= 9) { const tabs = document.querySelectorAll('.tab'); if (tabs[num - 1]) { e.preventDefault(); tabs[num - 1].click(); } } } // Ctrl+K: Focus calculator if (e.ctrlKey && e.key === 'k') { e.preventDefault(); const calcInput = document.querySelector('.tab-content.active .calc-input-field'); if (calcInput) calcInput.focus(); } // Ctrl+L: Focus first input field if (e.ctrlKey && e.key === 'l') { e.preventDefault(); const firstInput = document.querySelector('.tab-content.active .input-group input'); if (firstInput) firstInput.focus(); } // Alt+C: Clear all inputs in active tab if (e.altKey && e.key === 'c') { e.preventDefault(); const inputs = document.querySelectorAll('.tab-content.active .input-group input'); inputs.forEach(input => { if (!input.id.toLowerCase().includes('size') && !input.id.toLowerCase().includes('offset')) { input.value = ''; } }); // Trigger recalculation if (inputs.length > 0) { inputs[0].dispatchEvent(new Event('input', { bubbles: true })); } } // Ctrl+Shift+C: Copy all visible results if (e.ctrlKey && e.shiftKey && e.key === 'C') { e.preventDefault(); copyAllResults(); } }); // Show keyboard shortcuts hint showShortcutsHint(); } function showShortcutsHint() { // Create hint element if it doesn't exist if (document.getElementById('keyboard-hint')) return; const hint = document.createElement('div'); hint.id = 'keyboard-hint'; hint.className = 'keyboard-hint'; hint.innerHTML = ` ⌨️ `; document.body.appendChild(hint); // Toggle hint visibility hint.querySelector('.hint-toggle').addEventListener('click', () => { const content = hint.querySelector('.hint-content'); content.style.display = content.style.display === 'none' ? 'block' : 'none'; }); } function copyAllResults() { const results = []; const activeTab = document.querySelector('.tab-content.active'); if (!activeTab) return; const resultItems = activeTab.querySelectorAll('.result-item.available'); resultItems.forEach(item => { const label = item.querySelector('.result-label')?.textContent.trim(); const value = item.querySelector('.result-value')?.textContent.trim(); if (label && value && value !== '-') { results.push(`${label}: ${value}`); } }); if (results.length > 0) { const text = results.join('\n'); navigator.clipboard.writeText(text).then(() => { showNotification('Alle Ergebnisse kopiert!', 'success'); }); } } // ============================================ // 2. DOUBLE-CLICK TO COPY // ============================================ export function setupDoubleClickCopy() { document.addEventListener('dblclick', (e) => { // Check if double-clicked on a result value or any hex value const target = e.target; if (target.classList.contains('result-value') || target.classList.contains('conv-value') || target.closest('.result-value')) { const element = target.classList.contains('result-value') ? target : target.closest('.result-value'); const text = element.textContent.trim(); // Extract hex value const hexMatch = text.match(/0x[0-9a-fA-F]+/); if (hexMatch) { navigator.clipboard.writeText(hexMatch[0]).then(() => { highlightElement(element); showNotification('Kopiert: ' + hexMatch[0], 'success'); }); } } }); } function highlightElement(element) { element.style.transition = 'background-color 0.3s'; element.style.backgroundColor = '#4CAF50'; setTimeout(() => { element.style.backgroundColor = ''; }, 300); } // ============================================ // 3. COMPACT MODE TOGGLE // ============================================ export function setupCompactMode() { const toggle = document.createElement('button'); toggle.id = 'compact-mode-toggle'; toggle.className = 'compact-toggle'; toggle.innerHTML = '⚡ Kompakt'; toggle.title = 'Kompaktansicht umschalten'; // Insert toggle button in header const header = document.querySelector('.header-content .nav'); if (header) { const toggleContainer = document.createElement('div'); toggleContainer.appendChild(toggle); header.appendChild(toggleContainer); } // Load saved preference const isCompact = localStorage.getItem('compactMode') === 'true'; if (isCompact) { document.body.classList.add('compact-mode'); toggle.innerHTML = '🔍 Normal'; } toggle.addEventListener('click', () => { document.body.classList.toggle('compact-mode'); const isNowCompact = document.body.classList.contains('compact-mode'); toggle.innerHTML = isNowCompact ? '🔍 Normal' : '⚡ Kompakt'; localStorage.setItem('compactMode', isNowCompact); showNotification(isNowCompact ? 'Kompaktmodus aktiviert' : 'Normalmodus aktiviert', 'info'); }); } // ============================================ // 4. AUTO-CALCULATE ON PASTE // ============================================ export function setupAutoCalculateOnPaste() { document.addEventListener('paste', (e) => { const target = e.target; // Only handle paste in input fields if (target.tagName !== 'INPUT' || !target.closest('.input-group')) { return; } setTimeout(() => { // Trigger calculation after paste target.dispatchEvent(new Event('input', { bubbles: true })); showNotification('Wert eingefügt und berechnet', 'info'); }, 10); }); } // ============================================ // 5. ENHANCED COPY WITH FORMAT OPTIONS // ============================================ export function setupContextMenu() { let contextMenu = null; document.addEventListener('contextmenu', (e) => { const target = e.target; if (target.classList.contains('result-value') || target.classList.contains('conv-value')) { e.preventDefault(); const text = target.textContent.trim(); const hexMatch = text.match(/0x[0-9a-fA-F]+/); if (hexMatch) { const hexValue = hexMatch[0]; const decValue = parseInt(hexValue, 16); showContextMenu(e.pageX, e.pageY, hexValue, decValue); } } }); // Close menu on click outside document.addEventListener('click', () => { if (contextMenu) { contextMenu.remove(); contextMenu = null; } }); function showContextMenu(x, y, hexValue, decValue) { // Remove existing menu if (contextMenu) contextMenu.remove(); contextMenu = document.createElement('div'); contextMenu.className = 'context-menu'; contextMenu.style.left = x + 'px'; contextMenu.style.top = y + 'px'; const hexNoPrefix = hexValue.substring(2); const binary = '0b' + decValue.toString(2); const littleEndian = toLittleEndianBytes(decValue); contextMenu.innerHTML = `
Kopieren als:
Hex (0x) ${hexValue}
Hex (roh) ${hexNoPrefix}
Dezimal ${decValue}
Binär ${binary}
Little-Endian ${littleEndian}
`; document.body.appendChild(contextMenu); // Handle menu item clicks contextMenu.querySelectorAll('.context-menu-item').forEach(item => { item.addEventListener('click', (e) => { e.stopPropagation(); const value = item.getAttribute('data-value'); navigator.clipboard.writeText(value).then(() => { showNotification('Kopiert: ' + value, 'success'); contextMenu.remove(); contextMenu = null; }); }); }); } } function toLittleEndianBytes(value) { const bytes = []; let num = value; // Convert to 4-byte little-endian for (let i = 0; i < 4; i++) { bytes.push((num & 0xFF).toString(16).padStart(2, '0').toUpperCase()); num = num >> 8; } return bytes.join(' '); } // ============================================ // 6. NOTIFICATION SYSTEM // ============================================ function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification notification-${type}`; notification.textContent = message; document.body.appendChild(notification); // Trigger animation setTimeout(() => notification.classList.add('show'), 10); // Remove after 2 seconds setTimeout(() => { notification.classList.remove('show'); setTimeout(() => notification.remove(), 300); }, 2000); } // ============================================ // INITIALIZATION // ============================================ export function initializeUXEnhancements() { setupKeyboardShortcuts(); setupDoubleClickCopy(); setupCompactMode(); setupAutoCalculateOnPaste(); setupContextMenu(); console.log('✨ UX Enhancements activated!'); }