Detect when input box filled by keyboard and when by barcode scanner.
Solution 1
Well a barcode won't fire any key events so you could do something like:
$('#my_field').on({
keypress: function() { typed_into = true; },
change: function() {
if (typed_into) {
alert('type');
typed_into = false; //reset type listener
} else {
alert('not type');
}
}
});
Depending on when you want to evaluate this, you may want to do this check not on change but on submit, or whatever.
Solution 2
I wrote this answer, because my Barcode Scanner Motorola LS1203 generated keypress event, so I can't use Utkanos's solution.
My solution is:
var BarcodeScanerEvents = function() {
this.initialize.apply(this, arguments);
};
BarcodeScanerEvents.prototype = {
initialize: function() {
$(document).on({
keyup: $.proxy(this._keyup, this)
});
},
_timeoutHandler: 0,
_inputString: '',
_keyup: function (e) {
if (this._timeoutHandler) {
clearTimeout(this._timeoutHandler);
this._inputString += String.fromCharCode(e.which);
}
this._timeoutHandler = setTimeout($.proxy(function () {
if (this._inputString.length <= 3) {
this._inputString = '';
return;
}
$(document).trigger('onbarcodescaned', this._inputString);
this._inputString = '';
}, this), 20);
}
};
Solution 3
Adapted the super useful Vitall answer above to utilize an IIFE instead of prototyping, in case anyone just seeing this now is into that.
This also uses the 'keypress' event instead of keyup, which allowed me to reliably use KeyboardEvent.key, since KeyboardEvent.which is deprecated now. I found this to work for barcode scanning as well as magnetic-strip card swipes.
In my experience, handling card swipes with keyup caused me to do extra work handling 'Shift' keycodes e.g. a Shift code would be followed by the code representing '/', with the intended character being '?'. Using 'keypress' solved this as well.
(function($) {
var _timeoutHandler = 0,
_inputString = '',
_onKeypress = function(e) {
if (_timeoutHandler) {
clearTimeout(_timeoutHandler);
}
_inputString += e.key;
_timeoutHandler = setTimeout(function () {
if (_inputString.length <= 3) {
_inputString = '';
return;
}
$(e.target).trigger('altdeviceinput', _inputString);
_inputString = '';
}, 20);
};
$(document).on({
keypress: _onKeypress
});
})($);
Solution 4
you can try following example, using jQuery plugin https://plugins.jquery.com/scannerdetection/
Its highly configurable, time based scanner detector. It can be used as solution for prefix/postfix based, time based barcode scanner.
Tutorial for usage and best practices, as well discussed about various Barcode Scanner Models and how to deal with it. http://a.kabachnik.info/jquery-scannerdetection-tutorial.html
$(window).ready(function(){
//$("#bCode").scannerDetection();
console.log('all is well');
$(window).scannerDetection();
$(window).bind('scannerDetectionComplete',function(e,data){
console.log('complete '+data.string);
$("#bCode").val(data.string);
})
.bind('scannerDetectionError',function(e,data){
console.log('detection error '+data.string);
})
.bind('scannerDetectionReceive',function(e,data){
console.log('Recieve');
console.log(data.evt.which);
})
//$(window).scannerDetection('success');
<input id='bCode'type='text' value='barcode appears here'/>
Solution 5
For ES6 2019 version of Vitall answer.
const events = mitt()
class BarcodeScaner {
initialize = () => {
document.addEventListener('keypress', this.keyup)
if (this.timeoutHandler) {
clearTimeout(this.timeoutHandler)
}
this.timeoutHandler = setTimeout(() => {
this.inputString = ''
}, 10)
}
close = () => {
document.removeEventListener('keypress', this.keyup)
}
timeoutHandler = 0
inputString = ''
keyup = (e) => {
if (this.timeoutHandler) {
clearTimeout(this.timeoutHandler)
this.inputString += String.fromCharCode(e.keyCode)
}
this.timeoutHandler = setTimeout(() => {
if (this.inputString.length <= 3) {
this.inputString = ''
return
}
events.emit('onbarcodescaned', this.inputString)
this.inputString = ''
}, 10)
}
}
Can be used with react hooks like so:
const ScanComponent = (props) => {
const [scanned, setScanned] = useState('')
useEffect(() => {
const barcode = new BarcodeScaner()
barcode.initialize()
return () => {
barcode.close()
}
}, [])
useEffect(() => {
const scanHandler = code => {
console.log(code)
setScanned(code)
}
events.on('onbarcodescaned', scanHandler)
return () => {
events.off('onbarcodescaned', scanHandler)
}
}, [/* here put dependencies for your scanHandler ;) */])
return <div>{scanned}</div>
}
I use mitt from npm for events, but you can use whatever you prefer ;)
Tested on Zebra DS4208
WelcomeTo
Updated on January 27, 2022Comments
-
WelcomeTo about 2 years
How I can programmatically detect when text input filled by typing on keyboard and when it filled automatically by bar-code scanner?
-
WelcomeTo almost 12 yearsthanks. But how I can detect when barcode were input?
onCange
event rises only when element lost focus, but I need to know inserted value immediately after inserting. I can to make timer and periodically check value on text field, but I think it's wrong solution. -
Mitya almost 12 yearsYou didn't mention in your question when precisely you wanted to check input, so I assumed onChange. Yes, I think a timer is probably the only way there, unless the barcode application fires some sort of custom event when it manipulates the page.
-
chadiusvt over 5 yearsWanted to point out, this solution also fixes the first character missing bug that the answer from @Vitall had.
-
chadiusvt over 5 yearsAlso,
$(document).trigger(...
should be changed to$(e.target).trigger(...
so that the event registers with the desired DOM object. -
chadiusvt over 5 yearsThanks. Also, In my own usage, I noticed that some browsers (IE, Firefox) gave the value of
e.key
for keyboard keys like backspace to"BACKSPACE"
and trigger the event. I fixed this by addingif(e.key.length == 1) _inputString += e.key;
-
Aadam over 5 yearsThis is not working if focus is on input field, how can I avoid rfid typing it to input field and should only be detected in above code?
-
Tobia over 5 yearsI changed a bit the code moving the event from keyup to keydown and now you can avoid typing in the input field during barcode reading. Please try the fiddle.
-
sɐunıɔןɐqɐp over 5 yearsFrom Review: Welcome to Stack Overflow! Please don't answer just with source code. Try to provide a nice description about how your solution works. See: How do I write a good answer?. Thanks
-
Sharad over 4 yearsI tried in Android mobile bar code scanning, it is taking key press event only instead bar code scan? How this is working for you people.
-
Ahmad Karimi over 4 yearsVitall, I am not a JavaScript guy. I will be extremely grateful to know how this code works and how can I use it in my own code. I want to put an event listener for the $(document) element to catch anytime a barcode is scanned.
-
Vitall over 4 years@AhmadKarimi, for add event listener you just need to use jquery on method, something like
$(document).on( "onbarcodescaned", function(inputString) { // your code here in inputString should be barcode result });
-
Vitall over 4 years@AhmadKarimi also my answer is very old, try to use adapted version of code stackoverflow.com/a/56540835/527925
-
Baxny over 4 yearsIf your barcode scanner is slow (our bluetooth scanners) you may need to increase the timeout from 20 to a higher number. We changed our timeout to 200, to give the scanner more time to type the barcode in.
-
Baxny over 4 yearsWe also added a check to not type in special characters because when we were manually deleting the barcode out of the field, the script was typing the characters // Stop special keys inserting words e.g. backspace if (e.key.length == 1) { _inputString += e.key; }
-
Arman H about 4 yearsThanks I was looking for this. My-barcode Reader- inateck(p6 barcode scanner)
-
Jeppe over 3 yearsThis worked for me. To get the barcode-value, I had to subscribe to the trigger like this:
$(document).on("altdeviceinput", function (e, barCode) { ...
-
Joel over 3 yearsyou do not mention how that plugin will help in "Detecting when input box filled by keyboard and when by barcode scanner."
-
Jonathan B. about 3 yearsJust to clarify, this method works when the focus is not on an text input form element. If the focus IS on an input element, then we need to consider other factors as mentioned elsewhere in this Q&A.
-
khashashin about 3 years@jeppe thx to pointing on that. @spence7 could you please add some comments on your solution, it works well but I'm a bit confused with that
timeoutHandler
is that the timeout between keypresses? -
Spence7 about 3 years@khashashin The basic algorithm is: on the keypress event, cancel the setTimeout call if one is waiting to execute, add the pressed key value to an input buffer, then call setTimeout. If another keypress is not captured in 20ms, the function passed to setTimeout will be called. Said function will trigger an event IF the input string is at least 3 characters long (this combined with the short timeout was enough to indicate a scan). Either way the input buffer is flushed.
-
Christian Vermeulen over 2 yearsPerhaps this will make things easier? npmjs.com/package/@itexperts/barcode-scanner
-
Ogun Meriçligil over 2 yearsMy device Zebra MC2200 this worked for me thank you @Spence7 and Vitall
-
Malus Jan over 2 yearsThanks for the answer. Just one thing to add to the solution: if press enter the e.key will return
Enter
as a string and considered as scan. I modify the code like:if (e.charCode != 13) {_inputString += e.key;}