Detect when input box filled by keyboard and when by barcode scanner.

拈花ヽ惹草 提交于 2020-01-09 01:52:31

问题


How I can programmatically detect when text input filled by typing on keyboard and when it filled automatically by bar-code scanner?


回答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.




回答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);
    }
};



回答3:


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'/>



回答4:


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
    });
})($);



回答5:


If you can set a prefix to your barcode scanner I suggests this (I changed a bit the Vitall code):

var BarcodeScanner = function(options) {
     this.initialize.call(this, options);
};
BarcodeScanner.prototype = {
    initialize: function(options) {
       $.extend(this._options,options);
       if(this._options.debug) console.log("BarcodeScanner: Initializing");
       $(this._options.eventObj).on({
          keydown: $.proxy(this._keydown, this),
       });
    },
    destroy: function() {
        $(this._options.eventObj).off("keyup",null,this._keyup);
        $(this._options.eventObj).off("keydown",null,this._keydown);
    },
    fire: function(str){
        if(this._options.debug) console.log("BarcodeScanner: Firing barcode event with string: "+str);
        $(this._options.fireObj).trigger('barcode',[str]);
    },
    isReading: function(){
        return this._isReading;
    },
    checkEvent: function(e){
        return this._isReading || (this._options.isShiftPrefix?e.shiftKey:!e.shiftKey) && e.which==this._options.prefixCode;
    },
    _options: {timeout: 600, prefixCode: 36, suffixCode: 13, minCode: 32, maxCode: 126, isShiftPrefix: false, debug: false, eventObj: document, fireObj: document},
    _isReading: false,
    _timeoutHandler: false,
    _inputString: '',
    _keydown: function (e) {
        if(this._input.call(this,e))
            return false;
    },
    _input: function (e) {
        if(this._isReading){
            if(e.which==this._options.suffixCode){
                //read end
                if(this._options.debug) console.log("BarcodeScanner: Read END");
                if (this._timeoutHandler) 
                    clearTimeout(this._timeoutHandler);
                this._isReading=false;
                this.fire.call(this,this._inputString);
                this._inputString='';
            }else{
                //char reading
                if(this._options.debug) console.log("BarcodeScanner: Char reading "+(e.which));
                if(e.which>=this._options.minCode && e.which<=this._options.maxCode)
                    this._inputString += String.fromCharCode(e.which);
            }
            return true;
        }else{
            if((this._options.isShiftPrefix?e.shiftKey:!e.shiftKey) && e.which==this._options.prefixCode){
                //start reading
                if(this._options.debug) console.log("BarcodeScanner: Start reading");
                this._isReading=true;
                this._timeoutHandler = setTimeout($.proxy(function () {
                    //read timeout
                    if(this._options.debug) console.log("BarcodeScanner: Read timeout");
                    this._inputString='';
                    this._isReading=false;
                    this._timeoutHandler=false;
                }, this), this._options.timeout);
                return true;
            }
        }
        return false;
    }
};

If you need you customize timeout, suffix, prefix, min/max ascii code readed:

new BarcodeScanner({timeout: 600, prefixKeyCode: 36, suffixKeyCode: 13, minKeyCode: 32, maxKeyCode: 126});

I also added the isShiftPrefix option to use for example the $ char as prefix with these options: new BarcodeScanner({prefixKeyCode: 52, isShiftPrefix: true});

This is a fiddle: https://jsfiddle.net/xmt76ca5/




回答6:


You can use a "onkeyup" event on that input box. If the event has triggered then you can called it "Input from Keyboard".




回答7:


The solution from Vitall only works fine if you already hit at least one key. If you don't the first character will be ignored (if(this._timeoutHandler) returns false and the char will not be appended).

If you want to begin scanning immediately you can use the following code:

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);
	}
};



回答8:


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




回答9:


$(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'/>



回答10:


Hi I have and alternative solution for evaluate a result of the bar code scanner without use of jQuery, first you need and input text that have a focus the moment that the barcode scanner is works

<input id="input_resultado" type="text" />

The code in JavaScript is:

var elmInputScan = document.getElementById('input_resultado');           

elmInputScan.addEventListener('keypress', function (e){        
  clearInterval( timer_response );    
  timer_response = setTimeout( "onInputChange()", 10);
});    

When the barcode scanner input the text call serveral times to the keypress event, but only I interested to the final result, for this reason I use the timer. That's all, you can process the value into the onInputChange function.

function onInputChange() {    
  console.log( document.getElementById('input_resultado').value );
}


来源:https://stackoverflow.com/questions/11290898/detect-when-input-box-filled-by-keyboard-and-when-by-barcode-scanner

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!