Most USB and Bluetooth barcode scanners operate as keyboard-wedge devices: the scanner types the value into the focused field and usually sends Enter. A normal HTML form provides the most compatible starting point; JavaScript submits the scan without reloading the page.
Last updated: October 24, 2026.
<form id="scan-form">
<label for="barcode">Scan student barcode</label>
<input id="barcode" name="barcode" autocomplete="off" autofocus required>
<button type="submit">Record attendance</button>
</form>
<p id="status" role="status"></p>
<script>
const form = document.querySelector('#scan-form');
const input = document.querySelector('#barcode');
const status = document.querySelector('#status');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const barcode = input.value.trim();
if (!/^[A-Z0-9-]{4,64}$/i.test(barcode)) {
status.textContent = 'Invalid barcode.';
return;
}
const response = await fetch('/api/attendance', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ barcode })
});
status.textContent = response.ok ? 'Attendance recorded.' : 'Scan rejected.';
form.reset();
input.focus();
});
</script>The form submit event handles Enter from the scanner and a manual button press through the same path. Keep the field focused after each attempt so the next scan has an explicit destination.
Use ordinary form events before device APIs
The HTML form submit event is preferable to timing individual keystrokes. It works with keyboard-wedge scanners and preserves accessible form behavior. The keydown event is useful only when a special terminator or prefix needs separate handling.
Configure a suffix such as Enter when the scanner supports it. Do not assume every fast key sequence came from a scanner. WebHID can communicate with supported devices directly, but browser support is limited and permission is required. Reserve it for device-specific features.
Make the server authoritative
Authenticate the operator, validate the barcode, look up the student, and enforce one attendance record per student and session. An idempotency key or database constraint prevents a retry from creating a duplicate.
Disable the form while a request is in flight and show a clear result. Queue offline scans only when privacy and reconciliation rules are defined. Continue with handling Enter accessibly, preventing duplicate submissions, and calling a server route with Fetch.