Javascript: How to read a hand held barcode scanner best?

I'm little late but I made this work around based in some answers here.

let code = "";
let reading = false;

document.addEventListener('keypress', e => {
  //usually scanners throw an 'Enter' key at the end of read
   if (e.keyCode === 13) {
          if(code.length > 10) {
            console.log(code);
            /// code ready to use                
            code = "";
         }
    } else {
        code += e.key; //while this is not an 'enter' it stores the every key            
    }

    //run a timeout of 200ms at the first read and clear everything
    if(!reading) {
        reading = true;
        setTimeout(() => {
            code = "";
            reading = false;
        }, 200);  //200 works fine for me but you can adjust it
    }
});

After a lot of research and testing, what worked the best for me was to capture input from a barcode scanner without focusing a form input. Listen to the keydown and textInput events.

The textInput event acts like a paste event. It has then entire barcode data. In my case I am looking for UPC barcodes. The e.preventDefault() prevents the barcode data from being inserted into a form input:

document.addEventListener('textInput', function (e){
    if(e.data.length >= 6){
        console.log('IR scan textInput', e.data);
        e.preventDefault();
    }
});

I have tested this on Android 4.4 and 7.0 with a CipherLab IR scanner.

Example for listening to the keydown event. In my case I am able to assume that as long as a form input is not focused, the user is scanning a barcode.

    let UPC = '';
    document.addEventListener("keydown", function(e) {
        const textInput = e.key || String.fromCharCode(e.keyCode);
        const targetName = e.target.localName;
        let newUPC = '';
        if (textInput && textInput.length === 1 && targetName !== 'input'){
            newUPC = UPC+textInput;

          if (newUPC.length >= 6) {
            console.log('barcode scanned:  ', newUPC);
          } 
       }
    });

Of course, rather than checking the length of the string to determine a scan, you can listen for the e.keyCode === 13 in the keydown event listener.

Not all IR scanners will trigger the textInput event. If your device does not, then you can check to see if it is emitting something similar with:

monitorEvents(document.body);

Found this monitoring trick here: How do you log all events fired by an element in jQuery?


Your pseudo code won't work, because you don't have access to the scanner to catch events like scanButtonDown. Your only option is a HID scanner, which behaves exactly like a keyboard. To differentiate scanner input from keyboard input you have two options: Timer-based or prefix-based.

Timer-based

The scanner is likely to input characters much quicker than a user can (sensibly) with a keyboard. Calculate how quickly keystrokes are being received and buffer fast input into a variable to pass to your getProductsId function. @Vitall wrote a reusable jQuery solution for catching barcode scanner input, you would just need to catch the onbarcodescanned event.

Prefix-based

Most scanners can be configured to prefix all scanned data. You can use the prefix to start intercepting all input and once you've got your barcode you stop intercepting input.

Full disclosure: I work as a consultant to Socket Mobile, Inc. who make handheld scanners.