|
|
|
@@ -505,6 +505,10 @@
|
|
|
|
|
<input type="text" id="activeStudentCard" placeholder="Aktiver Ausweis (gescannt)" readonly>
|
|
|
|
|
<button id="resetCardBtn" class="button" type="button">Ausweis löschen</button>
|
|
|
|
|
<button id="toggleScannerBtn" class="button" type="button">Scanner starten</button>
|
|
|
|
|
<label style="display:flex; align-items:center; gap:8px; margin-left:6px;">
|
|
|
|
|
<input type="checkbox" id="keyboardScannerToggle">
|
|
|
|
|
<span style="font-size:0.9em;">Physischer Scanner</span>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="scanStatus" class="library-scan-status">
|
|
|
|
|
Hinweis: Im Schnellmodus zuerst den Schülerausweis scannen, danach den Buch-/Mediencode.
|
|
|
|
@@ -632,6 +636,11 @@
|
|
|
|
|
let activeStudentCardId = '';
|
|
|
|
|
let lastScanValue = '';
|
|
|
|
|
let lastScanAt = 0;
|
|
|
|
|
// Keyboard-scanner support (physical scanners that act as keyboard wedges)
|
|
|
|
|
let keyboardScannerEnabled = false;
|
|
|
|
|
let keyboardScanBuffer = '';
|
|
|
|
|
let keyboardLastKeyAt = 0;
|
|
|
|
|
const KEYBOARD_SCAN_INTERCHAR_MS = 100; // max time between keystrokes to consider them one scan
|
|
|
|
|
|
|
|
|
|
const canEditLibraryItems = (document.getElementById('libraryTableContainer')?.dataset.canEdit === '1');
|
|
|
|
|
|
|
|
|
@@ -912,6 +921,43 @@
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Keyboard scanner handling (physical scanners that send chars then Enter)
|
|
|
|
|
// =========================================================================
|
|
|
|
|
function keyboardScanKeydownHandler(e) {
|
|
|
|
|
// Only active when explicitly enabled
|
|
|
|
|
if (!keyboardScannerEnabled) return;
|
|
|
|
|
|
|
|
|
|
// Ignore if focus is in an input/textarea/contenteditable to avoid interfering with typing
|
|
|
|
|
const active = document.activeElement;
|
|
|
|
|
if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) return;
|
|
|
|
|
|
|
|
|
|
const now = Date.now();
|
|
|
|
|
|
|
|
|
|
// If Enter/Return pressed -> finalize buffer
|
|
|
|
|
if (e.key === 'Enter') {
|
|
|
|
|
const code = keyboardScanBuffer.trim();
|
|
|
|
|
keyboardScanBuffer = '';
|
|
|
|
|
keyboardLastKeyAt = 0;
|
|
|
|
|
if (!code) return;
|
|
|
|
|
// Process exactly like a camera scan
|
|
|
|
|
handleScanSuccess(code);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only accept common printable characters; ignore modifier keys
|
|
|
|
|
if (e.key.length === 1) {
|
|
|
|
|
// If time gap too big, start new buffer
|
|
|
|
|
if (keyboardLastKeyAt && (now - keyboardLastKeyAt) > KEYBOARD_SCAN_INTERCHAR_MS) {
|
|
|
|
|
keyboardScanBuffer = '';
|
|
|
|
|
}
|
|
|
|
|
keyboardScanBuffer += e.key;
|
|
|
|
|
keyboardLastKeyAt = now;
|
|
|
|
|
// Prevent default so scanner input doesn't accidentally move focus or trigger shortcuts
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleScanSuccess(decodedText) {
|
|
|
|
|
const scannedCode = normalizeScannedCode(decodedText);
|
|
|
|
|
if (!scannedCode) return;
|
|
|
|
@@ -1145,6 +1191,7 @@
|
|
|
|
|
const toggleBtn = document.getElementById('toggleScannerBtn');
|
|
|
|
|
const resetBtn = document.getElementById('resetCardBtn');
|
|
|
|
|
const modeSelect = document.getElementById('scanModeSelect');
|
|
|
|
|
const keyboardToggle = document.getElementById('keyboardScannerToggle');
|
|
|
|
|
|
|
|
|
|
if (toggleBtn) {
|
|
|
|
|
toggleBtn.addEventListener('click', async () => {
|
|
|
|
@@ -1172,6 +1219,19 @@
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (keyboardToggle) {
|
|
|
|
|
keyboardToggle.addEventListener('change', () => {
|
|
|
|
|
keyboardScannerEnabled = !!keyboardToggle.checked;
|
|
|
|
|
if (keyboardScannerEnabled) {
|
|
|
|
|
document.addEventListener('keydown', keyboardScanKeydownHandler);
|
|
|
|
|
setScanStatus('Physischer Scanner aktiv (Schnellmodus empfohlen).', 'ok');
|
|
|
|
|
} else {
|
|
|
|
|
document.removeEventListener('keydown', keyboardScanKeydownHandler);
|
|
|
|
|
setScanStatus('Physischer Scanner deaktiviert.', 'warn');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Run when DOM structure is entirely ready
|
|
|
|
|