【问题标题】:Detect when input box filled by keyboard and when by barcode scanner.检测输入框何时由键盘填充,何时由条形码扫描仪填充。
【发布时间】:2012-07-02 09:19:24
【问题描述】:

如何以编程方式检测何时通过键盘输入填充文本输入以及何时通过条形码扫描仪自动填充文本输入?

【问题讨论】:

    标签: javascript barcode-scanner


    【解决方案1】:

    我写了这个答案,因为我的 Barcode Scanner Motorola LS1203 生成了按键事件,所以我不能使用 Utkanos 的解决方案。

    我的解决办法是:

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

    【讨论】:

    • 重要的是,我不是 JavaScript 人。知道这段代码是如何工作的以及如何在我自己的代码中使用它,我将非常感激。我想为 $(document) 元素设置一个事件侦听器,以便在扫描条形码时捕获。
    • @AhmadKarimi,要添加事件侦听器,您只需要在方法上使用 jquery,例如 $(document).on( "onbarcodescaned", function(inputString) { // your code here in inputString should be barcode result });
    • @AhmadKarimi 我的答案也很老了,尝试使用改编版的代码stackoverflow.com/a/56540835/527925
    【解决方案2】:

    改编了超级有用的Vitall answer above 以利用 IIFE 而不是原型设计,以防万一现在看到这个的任何人都喜欢那个。

    这也使用 'keypress' 事件而不是 keyup,这使我能够可靠地使用 KeyboardEvent.key,因为 KeyboardEvent.which 现在已被弃用。我发现这适用于条形码扫描以及磁条卡刷卡。

    根据我的经验,使用 keyup 处理刷卡会导致我做额外的工作来处理“Shift”键码,例如Shift 代码后跟表示“/”的代码,预期的字符是“?”。使用'keypress'也解决了这个问题。

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

    【讨论】:

    • 想指出的是,这个解决方案还修复了@Vitall 的答案中的第一个字符丢失错误。
    • 另外,$(document).trigger(... 应更改为 $(e.target).trigger(...,以便事件注册到所需的 DOM 对象。
    • 谢谢。另外,在我自己的使用中,我注意到一些浏览器(IE、Firefox)将e.key 的值赋予"BACKSPACE" 等键盘键并触发事件。我通过添加if(e.key.length == 1) _inputString += e.key; 解决了这个问题
    • 这对我有用。要获得条形码值,我必须像这样订阅触发器:$(document).on("altdeviceinput", function (e, barCode) { ...
    • @khashashin 基本算法是:在 keypress 事件上,如果正在等待执行,则取消 setTimeout 调用,将按下的键值添加到输入缓冲区,然后调用 setTimeout。如果在 20 毫秒内没有捕获到另一个按键,则将调用传递给 setTimeout 的函数。如果输入字符串至少有 3 个字符长(这与短超时相结合足以指示扫描),则所述函数将触发事件。无论哪种方式,输入缓冲区都会被刷新。
    【解决方案3】:

    条形码不会触发任何关键事件,因此您可以执行以下操作:

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

    根据您想要评估的时间,您可能希望在提交时而不是在更改时进行检查。

    【讨论】:

    • 谢谢。但是我如何检测何时输入了条形码? onCange 事件仅在元素失去焦点时才会发生,但我需要在插入后立即知道插入的值。我可以制作计时器并定期检查文本字段的值,但我认为这是错误的解决方案。
    • 你没有在你的问题中提到你想要检查输入的确切时间,所以我假设 onChange。是的,我认为计时器可能是唯一的方法,除非条形码应用程序在操作页面时触发某种自定义事件。
    • 我在Android手机条码扫描中试过了,它只是采取按键事件而不是条码扫描?这对你们有什么作用。
    【解决方案4】:

    你可以试试下面的例子,使用jQuery插件https://plugins.jquery.com/scannerdetection/

    其高度可配置、基于时间的扫描仪检测器。它可以用作基于前缀/后缀、基于时间的条码扫描器的解决方案。

    使用和最佳实践教程,并讨论了各种条码扫描仪模型以及如何处理它。 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');
    &lt;input id='bCode'type='text' value='barcode appears here'/&gt;

    【讨论】:

    • 谢谢我在找这个。 My-barcode Readerinateck(p6条码扫描仪)
    【解决方案5】:

    对于 ES6 2019 版本的 Vitall 答案。

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

    可以像这样与反应钩子一起使用:

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

    我使用来自 npm 的 mitt 来处理事件,但你可以使用任何你喜欢的东西 ;)

    在 Zebra DS4208 上测试

    【讨论】:

      【解决方案6】:

      Vitall 的解决方案只有在您至少按下一个键的情况下才能正常工作。如果你不这样做,第一个字符将被忽略(if(this._timeoutHandler) 返回 false 并且不会附加字符)。

      如果您想立即开始扫描,可以使用以下代码:

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

      【讨论】:

        【解决方案7】:

        如果您可以为条形码扫描仪设置前缀,我建议您这样做(我更改了一点 Vitall 代码):

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

        如果您需要自定义超时、后缀、前缀、读取的最小/最大 ascii 码:

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

        我还添加了isShiftPrefix 选项以使用例如$ 字符作为这些选项的前缀:new BarcodeScanner({prefixKeyCode: 52, isShiftPrefix: true});

        这是一个小提琴:https://jsfiddle.net/xmt76ca5/

        【讨论】:

        • 如果焦点在输入字段上,这不起作用,我怎样才能避免 rfid 将其键入输入字段并且只能在上面的代码中检测到?
        • 我对将事件从 keyup 移动到 keydown 的代码进行了一些更改,现在您可以避免在读取条形码期间在输入字段中输入内容。请试试小提琴。
        【解决方案8】:

        您可以在该输入框上使用“onkeyup”事件。如果事件已触发,则可以将其称为“从键盘输入”。

        【讨论】:

          【解决方案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');
          &lt;input id='bCode'type='text' value='barcode appears here'/&gt;

          【讨论】:

          • 点评来源: 欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢
          【解决方案10】:

          您好,我有一个替代解决方案,可以在不使用 jQuery 的情况下评估条码扫描器的结果,首先您需要并输入在条码扫描器工作时具有焦点的文本

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

          JavaScript 中的代码是:

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

          当条形码扫描仪输入文本调用几次按键事件时,但只有我对最终结果感兴趣,因此我使用计时器。就是这样,您可以将值处理到 onInputChange 函数中。

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

          【讨论】:

            【解决方案11】:
            document.addEventListener("keypress", function (e) {
              if (e.target.tagName !== "INPUT") {
                // it's your scanner
              }
            });
            

            【讨论】:

            • 澄清一下,当焦点不在文本输入表单元素上时,此方法有效。如果重点是输入元素,那么我们需要考虑本问答中其他地方提到的其他因素。
            【解决方案12】:

            没有一个解决方案对我有用,因为我不想专注于输入。我希望结果页面(项目详细信息页面)继续监听扫描仪扫描下一个项目。我的扫描仪触发了按键事件,所以这对我来说就像一个魅力。

            var inputTemp = '';
            var inputTempInterval = setInterval(function() {
                // change 5 as minimum length of the scan code
                if (inputTemp.length >= 5) {
                    var detected = inputTemp;
                    inputTemp = '';
                    clearInterval(inputTempInterval); // stop listening if you don't need anymore
                    onScannerTrigger(detected);
                    
                } else {
                    inputTemp = '';
                }
                
            }, 100);
            
            $(window).keypress(function(e){   
                inputTemp += String.fromCharCode(e.which);
            });
            
            function onScannerTrigger(scannedCode) {
                console.log(scannedCode);
                // do your stuff
            }
            

            【讨论】:

            【解决方案13】:

            我发布了一个不依赖 jQuery 或输入字段的轻量级 JS 包。它简单地查看 keyPress 事件的时间来确定它是条形码扫描仪还是常规输入。

            https://www.npmjs.com/package/@itexperts/barcode-scanner

            import {BarcodeScanner} from "@itexperts/barcode-scanner";
            
            let options = {
              timeOut: 130,
              characterCount: 13
            }
            
            let barcodeScanner = new BarcodeScanner(options);
            barcodeScanner.addEventListener('scan', function(e){
                let barcode = e.detail;
                console.log(barcode);
            });
            

            【讨论】:

              【解决方案14】:

              我强烈推荐这个js插件https://github.com/axenox/onscan.js 它易于使用,并且有多种选项可以满足您的需求。

              <script src="path-to-onScan.js"></script>
              script>
              // Initialize with options
              onScan.attachTo(document, {
                  suffixKeyCodes: [13], // enter-key expected at the end of a scan
                  reactToPaste: true, // Compatibility to built-in scanners in paste-mode (as opposed to keyboard-mode)
                  onScan: function(sCode, iQty) { // Alternative to document.addEventListener('scan')
                      console.log('Scanned: ' + iQty + 'x ' + sCode); 
                  },
                  onKeyDetect: function(iKeyCode){ // output all potentially relevant key events - great for debugging!
                      console.log('Pressed: ' + iKeyCode);
                  }
              });
              </script>
              

              【讨论】:

              • 您没有提到该插件将如何帮助“检测输入框何时被键盘填充以及何时被条形码扫描仪填充。”
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-06-09
              • 2019-01-08
              • 1970-01-01
              • 1970-01-01
              • 2012-04-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多