当键盘输入框和条形码扫描仪填充时检测.

MyT*_*tle 23 javascript barcode-scanner

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

小智 27

我写了这个答案,因为我的条形码扫描仪摩托罗拉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);
    }
};
Run Code Online (Sandbox Code Playgroud)


Spe*_*ce7 9

改编上面超级有用的Vitall 答案以使用 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
    });
})($);
Run Code Online (Sandbox Code Playgroud)

  • 想指出的是,此解决方案还修复了@Vitall 的答案所具有的第一个字符缺失错误。 (2认同)
  • 这对我有用。为了获取条形码值,我必须像这样订阅触发器:`$(document).on("altdeviceinput", function (e, barCode) { ...` (2认同)
  • @khasashin 基本算法是:在按键事件上,如果正在等待执行,则取消 setTimeout 调用,将按下的键值添加到输入缓冲区,然后调用 setTimeout。如果在 20ms 内没有捕获到另一个按键,则将调用传递给 setTimeout 的函数。如果输入字符串至少有 3 个字符长(这与短超时相结合足以表明扫描),则该函数将触发事件。无论哪种方式,输入缓冲区都会被刷新。 (2认同)

Utk*_*nos 7

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

$('#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');
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

根据您要评估的时间,您可能希望执行此检查,而不是在更改时,而是在提交时,或其他任何内容.


dex*_*ini 7

您可以尝试使用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');
Run Code Online (Sandbox Code Playgroud)
<input id='bCode'type='text' value='barcode appears here'/>
Run Code Online (Sandbox Code Playgroud)


Mis*_*QQQ 7

对于 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)
  }
}
Run Code Online (Sandbox Code Playgroud)

可以像这样与 react hooks 一起使用:

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>
}
Run Code Online (Sandbox Code Playgroud)

我使用 npm 中的 mitt 进行事件,但您可以使用任何您喜欢的 ;)

在 Zebra DS4208 上测试