2
votes

Scope

I am attempting to detect character input from a barcode scanner integrated into a hand-held Android device in a simple web application using JavaScript. Since most barcode scanners behave like a keyboard wedge I am using detecting events keypress and/or keyup to interpret and handle the character input.

I don't want the character input to populate a text input, so I have assigned the event handler to document, however, I know I could also assign it to the window.

Sample Code

My sample code for completing the task looks like this; This sample doesn't differentiate between keyboard input and scanner input, but I have already solved that problem.

var barcodeString = "";

$(document).keypress(function (event) {
    // If character is carriage-return prevent submit.
    if (event.which === 13) {
        event.preventDefault();
    }
    // Append other characters to barcodeString.
    barcodeString += event.key;
});

Problem

My problem is that many devices do not return any readable characters at all. When I monitor the character codes using event.keyCode I receive two codes: 229 and 13. This article W3 keyCode in key events and this StackOverflow answer Is it OK to ignore keydown events with keyCode = 229? outlines that the 229 code means the Input Monitor is busy. I can only assume this is either because:

  • The barcode scanner locks the Input Monitor upon inserting the characters.
  • The speed of the character input causes the Input Monitor to become too busy to detect character input.

Interestingly enough, if I detect event.keyCode while scanning the text into a text input, the two character codes: 229 and 13 are detected and only afterward the text is then inserted into the text input.

Devices

The devices I am attempting to implement this on are Nautiz X2 made by the Handheld Group. And another Android device, which I am unable to identify the brand of but seems slightly more generic with different barcode scanning software.

Workarounds

1

The Handheld Group do provide a JavaScript API for interacting with the Handheld Scanner. The way this works is they provide an APK for a custom browser named: Kiosk Browser and implement the interpretation of the JavaScript specific to the scanner there. Documentation can be found here (it's exceedingly short and not a long read): JavaScript Scanner Interface

2

The more generic Android device has the ability to 'slow-down' character input on the scanner to make the scanner more compatible with third-party applications. Behold, toggling this option allows me to detect character input. Although event.key always returns code 229 (this time from an unreadable character), but String.fromCharCode(event.which) will somewhat solve the problem (it doesn't deal with special characters). The Nautiz X2 does not have the option to 'slow-down' input in the software settings.

3

The alternative workaround I have considered is putting a text input onto the web page with the style display: none to hide it and use JavaScript to continually set focus on the input. The I can attempt to monitor onChange and handle the character input. I would really like to avoid this approach.

Summary

The workarounds I have presented seem awful and the first is not device independent. I was wondering if there is a better place to "dump" text input from the barcode scanner so I can handle it in my application? Or, is there an event I can monitor to detect the character input?

1
Did you ever solve this? :D I'm having this exact problem right now. no workarounds of yours are feasible. constantly focusing the input (workaround3) keeps opening the android soft keyboard on the scannerKasper Sølvstrøm

1 Answers

0
votes

I know this is late, but I am facing a similar problem with a range of devices including the Zebra TC20 and Chainway C71. After a lot of searching around I found this amazing Codepen sample by Bob Jase. He has documented his solution in the code, but I'll repost it here for archive purposes. link to his CodePen

His solution uses a hidden element to change the focus to from a visible element and thus hiding the soft android keyboard.

// whenever the visible field gets focused
$("#visibleField").bind("focus", function(e) {
  // silently shift the focus to the hidden select box
  $("#hiddenField").focus();
  $("#cursorMeasuringDiv").css("font", $("#visibleField").css("font"));
});

// whenever the user types on his keyboard in the select box
// which is natively supported for jumping to an <option>
$("#hiddenField").bind("keypress",function(e) {
  // get the current value of the readonly field
  var currentValue = $("#visibleField").val();
  
  // and append the key the user pressed into that field
  $("#visibleField").val(currentValue + e.key);
  $("#cursorMeasuringDiv").text(currentValue + e.key);
  
  // measure the width of the cursor offset
  var offset = 3;
  var textWidth = $("#cursorMeasuringDiv").width();
  $("#hiddenField").css("marginLeft",Math.min(offset+textWidth,$("#visibleField").width()));
  
});
#hiddenField {
  height:17px; 
  width:1px;
  position:absolute;
  margin-left:3px;
  margin-top:2px;
  border:none;
  border-width:0px 0px 0px 1px;
}

#cursorMeasuringDiv {
  position:absolute;
  visibility:hidden;
  margin:0px;
  padding:0px;
}

#hiddenField:focus {
  border:1px solid gray;  
  border-width:0px 0px 0px 1px;
  outline:none;
  animation-name: cursor;
  animation-duration: 1s;
  animation-iteration-count: infinite;
}

@keyframes cursor {
    from {opacity:0;}
    to {opacity:1;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click on the field and type (it should work even though the field isn't really focused): 
<p />

<!-- must be a select box with no children to suppress the keyboard -->
input: <select id="hiddenField" /> 
<span id="fakecursor" />

<input type="text" readonly="readonly" id="visibleField" />
<div id="cursorMeasuringDiv" />

I hope this helps. Again, kudos to Bob for working this out!