Javascript:如何最好地阅读手持式条形码扫描仪?

Mr.*_* B. 26 javascript ajax jquery barcode-scanner angularjs

我希望能够通过手持式扫描仪扫描条形码并使用Javascript处理结果.

条形码扫描仪几乎像键盘一样工作.它输出扫描/翻译(条形码 - >数字)数据原始(对吗?).实际上我只需要捕获输出并继续.但是怎么样?

这是我想做的一些伪代码:

$(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>");
});
Run Code Online (Sandbox Code Playgroud)
  • 任何想法(框架,插件,片段)?
  • 任何条码扫描仪(硬件)推荐?

提前致谢!

我发现了这个这个好问题,但我想获得有关处理的更多信息.在我的案例中,仅仅关注textarea可能是不够的.

Enr*_*ico 26

您的伪代码将无法正常工作,因为您无权访问扫描程序以捕获类似的事件scanButtonDown.您唯一的选择是HID扫描仪,其行为与键盘完全相同.要区分扫描仪输入和键盘输入,您有两种选择:基于定时器或基于前缀.

基于定时器

扫描仪可能比使用键盘(明智地)更快地输入字符.计算接收击键的速度,并将快速输入缓冲到变量中以传递给您的getProductsId函数.@Vitall写了一个可重用的jQuery解决方案来捕获条形码扫描器输入,你只需要捕获onbarcodescanned事件.

前缀为基础

大多数扫描仪可以配置为所有扫描数据的前缀.您可以使用前缀开始拦截所有输入,一旦获得条形码,就可以停止拦截输入.

完全披露:我是Socket Mobile,Inc.的顾问,负责制造手持式扫描仪.

  • 我知道这是一篇旧帖子,但也想指出 HID 扫描仪也可能在输入末尾使用返回字符/键。 (2认同)
  • @yeouuu 检查您的扫描仪文档。通常有一种方法可以禁用它,但它因扫描仪而异。或者,由于您正在捕获每个键事件,您可以使用 `preventDefault` 在每次扫描结束时“吞下”返回/输入键 (2认同)

小智 10

我有点晚了,但我根据这里的一些答案完成了这项工作。

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

  • 如果您正在寻找某些东西,这是可以使用的解决方案。请注意,并非所有扫描仪都是一样的。对于某些蓝牙/更便宜的扫描仪来说,200 毫秒的超时可能不够。我建议允许客户调整此设置以满足他们的需求。 (3认同)

jfb*_*m22 8

经过大量的研究和测试,对我来说最有效的方法是从条形码扫描仪捕获输入,而无需关注表单输入。收听keydowntextInput事件。

textInput事件就像paste事件一样。然后,它具有完整的条形码数据。就我而言,我正在寻找UPC条形码。该e.preventDefault()被插入一个形式输入防止条形码数据:

document.addEventListener('textInput', function (e){
    if(e.data.length >= 6){
        console.log('IR scan textInput', e.data);
        e.preventDefault();
    }
});
Run Code Online (Sandbox Code Playgroud)

我已经使用CipherLab IR扫描仪在Android 4.4和7.0上对此进行了测试。

收听keydown事件的示例。在我的情况下,我可以假设只要表单输入未聚焦,用户就在扫描条形码。

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

当然,您可以e.keyCode === 13keydown事件侦听器中侦听而不是检查字符串的长度来确定扫描。

并非所有的红外扫描仪都会触发该textInput事件。如果您的设备没有,则可以检查它是否发出类似以下内容的信号:

monitorEvents(document.body);
Run Code Online (Sandbox Code Playgroud)

在这里找到了这个监视技巧: 如何记录jQuery中某个元素触发的所有事件?

  • 很高兴听到你成功了!仅供参考,您的项目链接末尾有一个额外的“i”。 (2认同)

Que*_*tin 6

条形码扫描仪的工作原理几乎就像键盘一样。

这取决于型号。我用过的每一个都像键盘一样工作(至少就计算机而言)

它输出扫描/翻译的(条形码->数字)原始数据(对吗?)。

它输出键码。

$(document).on("scanButtonDown"
Run Code Online (Sandbox Code Playgroud)

你可能想要keypress,但不想要scanButtonDown

查看事件对象以确定按下的“键”。

要确定整个代码何时被扫描,您可能会得到一个“数据结束”键(可能是空格或回车),或者您可能只需要计算正在输入的字符数。


Fra*_*erZ 6

好的,这就是我的做法。我设置了扫描仪,以添加前缀(在我的情况下,我使用Ctrl + 2或ASCII代码002(控制代码),因此无法通过键盘轻松输入)和ENTER(可以随意如果您的条形码数据可能包含回车,请将其更改为在每次条形码扫描后使用Ctrl + 3或ASCII代码003之类的内容。在jQuery中,我捕获了keypress事件,并查找了前缀。然后,将所有内容捕获到一个字符串中,然后触发一个自定义事件,我的应用程序可以监听该事件。因为我要防止按键事件,所以用户可以在文本字段中扫描条形码,这可以触发事件而不会影响他们正在做的任何事情。

此外,每个条形码都有一个1位数的前缀,我们可以用来识别扫描条形码的类型。例子:

  • E:员工证
  • S:主管徽章
  • I:商品编号
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);
Run Code Online (Sandbox Code Playgroud)

由于有了这个前缀,我现在可以识别条形码的类型,并查看是否应在此页面上处理它。例:

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


roh*_*hit 6

尝试了所有解决方案,但没有达到预期效果。我在scan.js 上找到了最简单的解决方案,我有使用 Angular 8 的应用程序。

非常简单且良好的实施。

对于 Angular 8,我遵循以下步骤:

1.npm安装onscan.js --save

2.打开 angular.json,在脚本数组中添加一项作为“node_modules/onscan.js/onscan.min.js”

3.在组件类中,实现AfterViewInit接口

declare var onscan:any;
  ngAfterViewInit(): void {

    //Put focus to textbox and press scanner button
    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);
      },
    });
  }
Run Code Online (Sandbox Code Playgroud)

最好的事情是扫描的文本出现在聚焦的文本框元素中

希望这有帮助。


小智 5

我也想使用 React 来分享这个主题,因为我在这方面遇到了很多困难。我认为大多数条形码扫描仪,如 Hanz Herdel 所说,以 ENTER 终止。就我而言,我发现将输入包装在表单中并捕获提交事件、防止默认值并检索输入的值更容易。
我更喜欢这种类型的方法,以便处理任何类型的条形码长度,而不是检查它的长度。

这是我在 React 中的处理方式:

import { useState } from "react";

export default function Modal() {
const [repairArticles, setRepairArticles] = useState([]);

function handleBarcodeInput(e) {
  e.preventDefault();
  const input = e.target.querySelector("input");
  const value = input.value;
  setRepairArticles((prev) => {
    return (prev = [...prev, value]);
  });
  input.value = "";
}

return (
  <div>
    <form onSubmit={(e) => handleBarcodeInput(e)} >
      <input id="barcode-input" />
      <button type="submit" className="hidden" />
    </form>
    <div className="mt-3">
      {repairArticles.map((el, index) => {
        return <p key={index}>{el}</p>;
      })}
    </div>
  </div>    
 )           
}
Run Code Online (Sandbox Code Playgroud)