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

I'd like to be able to scan barcodes via a hand held scanner and handle the results with Javascript.

A barcode-scanner works almost like a keyboard. It outputs the scanned/translated (barcode->number) data raw (right?). Actually I just need to catch the output and proceed. But how?

Here's some pseudocode I'd like to make work:

$(document).on("scanButtonDown", "document", function(e) {
    // get scanned content
    var scannedProductId = this.getScannedContent();

    // get product 
    var product = getProductById(scannedProductId);

    // add productname to list
    $("#product_list").append("<li>" + product.name + "</li>");
});
  • Any ideas (frameworks, plugins, snippets)?
  • Any barcode-scanner (hardware) recommendation?

Thanks in advance!

I found this and this good questions but I'd like to get more information about the handling. Just to focus a textarea may be not enough in my case.

Answers:

Answer

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.

Answer

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?

Answer

OK, so here's how I did it. I set up the scanner, to add a prefix (In my case, I used Ctrl+2 or the ascii code 002 (a control code) so it couldn't easily be entered via keyboard), and an ENTER, (Feel free to change this to use something like Ctrl+3 or ascii code 003 after each barcode scan, if your barcode data may contain enters). In jQuery, I capture the keypress event, and look for the prefix. I then, capture everything into a string, and then fire a custom event, that my app can listen for. Because I'm preventing the keypress event, the user can be in a text field, and scan a barcode, which can trigger an event without affecting anything they're doing.

Additionally, each barcode has a 1 digit prefix that we use, to identify the type of barcode scanned. Examples:

  • E: Employee Badge
  • S: Supervisor Badge
  • I: Item Number
let barcodeRead = '';
let readingBarcode = false;

let handleKeyPress = (e) => {
    if (e.keyCode === 2) {
        // Start of barcode
        readingBarcode = true;
        e.preventDefault();
        return;
    }

    if (readingBarcode) {
        e.preventDefault();

        if (e.keyCode === 13) { // Enter
            readingBarcode = false;
            const evt = $.Event('barcodeScan');
            evt.state = {
                type: barcodeRead.substr(0, 1),
                code: barcodeRead.substr(1),
            };
            $(window).trigger(evt);
            barcodeRead = '';
            return;
        }

        // Append the next key to the end of the list
        barcodeRead += e.key;
    }
}

$(window).bind('keypress', handleKeyPress);

Because of this prefix, I can now identify the type of barcode, and see if it should be handled on this page. Example:

$(window).bind('barcodeScan', (e) => {
    if (e.state.type !== 'E') {
        alert('Please scan your employee badge only!');
    } else {
        $('#employee-badge').val(e.state.code);
    }
});
Answer

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
Answer

A barcode-scanner works almost like a keyboard.

It depends on the model. Every one that I've used works exactly like a keyboard (at least as far as the computer is concerned)

It outputs the scanned/translated (barcode->number) data raw (right?).

It outputs keycodes.

$(document).on("scanButtonDown"

You probably want keypress, not scanButtonDown.

Look at the event object to determine the "key" that was pressed.

To determine when the entire code has been scanned, you might get an "end of data" key (possibly a space or a return) or you might have to just count how many characters are being input.

Answer

I've just started working on a plugin that handles barcode scanning and credit card scanning (built on jQuery):

https://github.com/ericuldall/jquery-pos

Simple implementation:

$(function(){
    $(document).pos();
    $(document).on('scan.pos.barcode', function(event){
        var barcode = event.code;
        //handle your code here....
    });
});

So far this plugin is only tested with one type of scanner and codes containing only digits, but if you have further requirements that aren't working with it, I'd be happy to adapt it to your needs. Please check out the github page and give it a whirl. Contributions are encouraged.

E

Answer

var txt = "";
function selectBarcode() {
    if (txt != $("#focus").val()) {
        setTimeout('use_rfid()', 1000);
        txt = $("#focus").val();
    }
    $("#focus").select();
    setTimeout('selectBarcode()', 1000);
}

$(document).ready(function () {
    setTimeout(selectBarcode(),1000);       
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 

<input type="text" name="tag" id="focus" placeholder="Use handheld RFID scanner">

Answer

This is an extension to the answer given by Hanz Herdel incase you are using one of the PosX scanners or any other scanner that are capable of adding a special symbol to the beginning of the characters. In this case, the tilde (~) symbol:

let barcode = "";
let reading = false;

document.addEventListener("keydown", e => {
	//console.log(e.key);
	
	if (e.key == 'Enter') {
		if (barcode.length == 17) {
			if (barcode.charAt(0) == '~') {
				
				console.log(barcode);
				barcode = "";
			}
		}
	}
	else {
		if (e.key != 'Shift') {
			barcode += e.key;
		}
	}
	
	if (!reading) {
		reading = true;
		setTimeout( () => {
			barcode = "";
			reading = false;
		}, 200);
	}
}, true)

You can change the barcode length and the timeout speed to your liking but this worked perfect for me.

Answer

Here is working fine.
It's working when input has focus and input hasn't focus

on_scanner() // init function

function on_scanner() {
    let is_event = false; // for check just one event declaration
    let input = document.getElementById("scanner");
    input.addEventListener("focus", function () {
        if (!is_event) {
            is_event = true;
            input.addEventListener("keypress", function (e) {
                setTimeout(function () {
                    if (e.keyCode == 13) {
                        scanner(input.value); // use value as you need
                        input.select();
                    }
                }, 500)
            })
        }
    });
    document.addEventListener("keypress", function (e) {
        if (e.target.tagName !== "INPUT") {
            input.focus();
        }
    });
}

function scanner(value) {
    if (value == '') return;
    console.log(value)
}

HTML

<input type="text" id="scanner" placeholder="scanner">

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.