Files
delphi-database/static/js/keyboard-shortcuts.js
HotSwapp c2f3c4411d progress
2025-08-09 16:37:57 -05:00

464 lines
13 KiB
JavaScript

/**
* Keyboard Shortcuts for Delphi Consulting Group Database System
* Replicates legacy Pascal system shortcuts for user familiarity
*/
let keyboardShortcutsEnabled = true;
function initializeKeyboardShortcuts() {
document.addEventListener('keydown', handleKeyboardShortcuts);
console.log('Keyboard shortcuts initialized');
}
function handleKeyboardShortcuts(event) {
if (!keyboardShortcutsEnabled) {
return;
}
// Don't process shortcuts if user is typing in input fields
const activeElement = document.activeElement;
const isInputField = ['INPUT', 'TEXTAREA', 'SELECT'].includes(activeElement.tagName) ||
activeElement.contentEditable === 'true';
// Allow specific shortcuts even in input fields
const allowedInInputs = ['F1', 'Escape'];
const keyName = getKeyName(event);
if (isInputField && !allowedInInputs.includes(keyName)) {
return;
}
// Handle shortcuts based on key combination
const shortcut = getShortcutKey(event);
switch (shortcut) {
// Help
case 'F1':
event.preventDefault();
showHelp();
break;
// Navigation shortcuts
case 'Alt+C':
event.preventDefault();
navigateTo('/customers');
break;
case 'Alt+F':
event.preventDefault();
navigateTo('/files');
break;
case 'Alt+L':
event.preventDefault();
navigateTo('/financial');
break;
case 'Alt+D':
event.preventDefault();
navigateTo('/documents');
break;
case 'Alt+A':
event.preventDefault();
navigateTo('/admin');
break;
// Global search
case 'Ctrl+F':
event.preventDefault();
focusGlobalSearch();
break;
// Form shortcuts
case 'Ctrl+N':
event.preventDefault();
newRecord();
break;
case 'Ctrl+S':
event.preventDefault();
saveRecord();
break;
case 'F9':
event.preventDefault();
editMode();
break;
case 'F2':
event.preventDefault();
completeAction();
break;
case 'F8':
event.preventDefault();
clearForm();
break;
case 'Delete':
if (!isInputField) {
event.preventDefault();
deleteRecord();
}
break;
case 'Escape':
event.preventDefault();
cancelAction();
break;
// Legacy system shortcuts
case 'F10':
event.preventDefault();
showMenu();
break;
case 'Alt+M':
event.preventDefault();
showMemo();
break;
case 'Alt+T':
event.preventDefault();
toggleTimer();
break;
case 'Alt+B':
event.preventDefault();
showBalanceSummary();
break;
// Quick creation shortcuts
case 'Ctrl+Shift+C':
event.preventDefault();
newCustomer();
break;
case 'Ctrl+Shift+F':
event.preventDefault();
newFile();
break;
case 'Ctrl+Shift+T':
event.preventDefault();
newTransaction();
break;
// Date navigation (legacy system feature)
case '+':
if (!isInputField && isDateField(activeElement)) {
event.preventDefault();
changeDateBy(1);
}
break;
case '-':
if (!isInputField && isDateField(activeElement)) {
event.preventDefault();
changeDateBy(-1);
}
break;
// Table navigation
case 'ArrowUp':
if (!isInputField && isInTable()) {
event.preventDefault();
navigateTable('up');
}
break;
case 'ArrowDown':
if (!isInputField && isInTable()) {
event.preventDefault();
navigateTable('down');
}
break;
case 'PageUp':
if (!isInputField && isInTable()) {
event.preventDefault();
navigateTable('pageup');
}
break;
case 'PageDown':
if (!isInputField && isInTable()) {
event.preventDefault();
navigateTable('pagedown');
}
break;
case 'Home':
if (!isInputField && isInTable()) {
event.preventDefault();
navigateTable('home');
}
break;
case 'End':
if (!isInputField && isInTable()) {
event.preventDefault();
navigateTable('end');
}
break;
case 'Enter':
if (!isInputField && isInTable()) {
event.preventDefault();
openRecord();
}
break;
}
}
function getShortcutKey(event) {
const parts = [];
if (event.ctrlKey) parts.push('Ctrl');
if (event.altKey) parts.push('Alt');
if (event.shiftKey) parts.push('Shift');
let key = event.key;
// Handle special keys
switch (event.keyCode) {
case 112: key = 'F1'; break;
case 113: key = 'F2'; break;
case 114: key = 'F3'; break;
case 115: key = 'F4'; break;
case 116: key = 'F5'; break;
case 117: key = 'F6'; break;
case 118: key = 'F7'; break;
case 119: key = 'F8'; break;
case 120: key = 'F9'; break;
case 121: key = 'F10'; break;
case 122: key = 'F11'; break;
case 123: key = 'F12'; break;
case 46: key = 'Delete'; break;
case 27: key = 'Escape'; break;
case 33: key = 'PageUp'; break;
case 34: key = 'PageDown'; break;
case 35: key = 'End'; break;
case 36: key = 'Home'; break;
case 37: key = 'ArrowLeft'; break;
case 38: key = 'ArrowUp'; break;
case 39: key = 'ArrowRight'; break;
case 40: key = 'ArrowDown'; break;
case 13: key = 'Enter'; break;
case 187: key = '+'; break; // Plus key
case 189: key = '-'; break; // Minus key
}
parts.push(key);
return parts.join('+');
}
function getKeyName(event) {
switch (event.keyCode) {
case 112: return 'F1';
case 27: return 'Escape';
default: return event.key;
}
}
// Navigation functions
function navigateTo(url) {
window.location.href = url;
}
function focusGlobalSearch() {
const searchInput = document.querySelector('#global-search, .search-input, [name="search"]');
if (searchInput) {
searchInput.focus();
searchInput.select();
} else {
navigateTo('/search');
}
}
// Form action functions
function newRecord() {
const newBtn = document.querySelector('.btn-new, [data-action="new"], .bg-primary-600[href*="new"]');
if (newBtn) {
newBtn.click();
} else {
showToast('New record shortcut not available on this page', 'info');
}
}
function saveRecord() {
const saveBtn = document.querySelector('.btn-save, [data-action="save"], .bg-green-600[type="submit"]');
if (saveBtn) {
saveBtn.click();
} else {
// Try to submit the main form
const form = document.querySelector('form.main-form, form');
if (form) {
form.submit();
} else {
showToast('Save shortcut not available on this page', 'info');
}
}
}
function editMode() {
const editBtn = document.querySelector('.btn-edit, [data-action="edit"]');
if (editBtn) {
editBtn.click();
} else {
showToast('Edit mode shortcut not available on this page', 'info');
}
}
function completeAction() {
const completeBtn = document.querySelector('.btn-complete, [data-action="complete"], .bg-primary-600');
if (completeBtn) {
completeBtn.click();
} else {
saveRecord(); // Fallback to save
}
}
function clearForm() {
const clearBtn = document.querySelector('.btn-clear, [data-action="clear"]');
if (clearBtn) {
clearBtn.click();
} else {
// Clear all form inputs
const form = document.querySelector('form');
if (form) {
form.reset();
showToast('Form cleared', 'info');
}
}
}
function deleteRecord() {
const deleteBtn = document.querySelector('.btn-delete, [data-action="delete"], .bg-danger-600');
if (deleteBtn) {
deleteBtn.click();
} else {
showToast('Delete shortcut not available on this page', 'info');
}
}
function cancelAction() {
// Close modals first
// Close Tailwind-style modals
const openModal = document.querySelector('.fixed.inset-0:not(.hidden)');
if (openModal) {
openModal.classList.add('hidden');
return;
}
// Then try cancel buttons
const cancelBtn = document.querySelector('.btn-cancel, [data-action="cancel"], .bg-neutral-100');
if (cancelBtn) {
cancelBtn.click();
} else {
window.history.back();
}
}
// Legacy system specific functions
function showHelp() {
const helpModal = document.querySelector('#shortcutsModal');
if (helpModal) {
helpModal.classList.remove('hidden');
} else {
showToast('Press F1 to see keyboard shortcuts', 'info');
}
}
function showMenu() {
// Toggle Tailwind mobile menu if available
if (typeof toggleMobileMenu === 'function') {
toggleMobileMenu();
return;
}
const mobileMenu = document.getElementById('mobileMenu');
if (mobileMenu) {
mobileMenu.classList.toggle('hidden');
return;
}
showToast('Menu (F10) - Use Alt+C, Alt+F, Alt+L, Alt+D for navigation', 'info');
}
function showMemo() {
const memoBtn = document.querySelector('[data-action="memo"], .btn-memo');
if (memoBtn) {
memoBtn.click();
} else {
showToast('Memo function not available on this page', 'info');
}
}
function toggleTimer() {
const timerBtn = document.querySelector('[data-action="timer"], .btn-timer');
if (timerBtn) {
timerBtn.click();
} else {
showToast('Timer function not available on this page', 'info');
}
}
function showBalanceSummary() {
const balanceBtn = document.querySelector('[data-action="balance"], .btn-balance');
if (balanceBtn) {
balanceBtn.click();
} else {
showToast('Balance summary not available on this page', 'info');
}
}
// Quick creation functions
function newCustomer() {
navigateTo('/customers/new');
}
function newFile() {
navigateTo('/files/new');
}
function newTransaction() {
navigateTo('/financial/new');
}
// Utility functions
function isDateField(element) {
if (!element) return false;
return element.type === 'date' ||
element.classList.contains('date-field') ||
element.getAttribute('data-type') === 'date';
}
function isInTable() {
const activeElement = document.activeElement;
return activeElement && (
activeElement.closest('table') ||
activeElement.classList.contains('table-row') ||
activeElement.getAttribute('role') === 'gridcell'
);
}
function changeDateBy(days) {
const activeElement = document.activeElement;
if (isDateField(activeElement)) {
const currentDate = new Date(activeElement.value || Date.now());
currentDate.setDate(currentDate.getDate() + days);
activeElement.value = currentDate.toISOString().split('T')[0];
activeElement.dispatchEvent(new Event('change', { bubbles: true }));
}
}
function navigateTable(direction) {
// Table navigation implementation would depend on the specific table structure
showToast(`Table navigation: ${direction}`, 'info');
}
function openRecord() {
const activeElement = document.activeElement;
const row = activeElement.closest('tr, .table-row');
if (row) {
const link = row.querySelector('a, [data-action="open"]');
if (link) {
link.click();
}
}
}
function showToast(message, type = 'info') {
if (window.alerts && typeof window.alerts.show === 'function') {
window.alerts.show(message, type, { duration: 3000 });
return;
}
// Fallback
alert(String(message));
}
// Export for use in other scripts
window.keyboardShortcuts = {
initialize: initializeKeyboardShortcuts,
enable: () => { keyboardShortcutsEnabled = true; },
disable: () => { keyboardShortcutsEnabled = false; },
showHelp: showHelp
};