How to detect programmatic value change on input field - javascript

I've read several questions [1], [2], [3] regarding this topic, but none seems to provide a general solution to this problem. All answers seems to be directed to some specific cases.
I have this simple input field
<input type="number" id="inputBox" min="0" max="255" step="1" />
and I do a strict input validation on it:
inputBox.addEventListener("input", function () {
validateInput(this);
});
inputBox.addEventListener("keydown", function (e) {
validateInput(this, e);
});
function validateInput(elm, e) {
// handle keydown event
if (e) {
// do not allow floating-point numbers, if it's not expected
if (!isFloat(elm.step)) {
if (e.key == ".") {
e.preventDefault();
}
}
}
// handle input event
else {
// do not allow leading zeros
while (elm.value.length > 1 && elm.value[0] === "0") {
elm.value = elm.value.toString().slice(1);
}
// input should be between min and max
if (elm.validity.rangeUnderflow) {
elm.value = elm.min;
}
else if (elm.validity.rangeOverflow) {
elm.value = elm.max;
}
}
}
All this seems to be working fine for user input.
var inputBox = document.getElementById("inputBox");
inputBox.addEventListener("input", function() {
validateInput(this);
});
inputBox.addEventListener("keydown", function(e) {
validateInput(this, e);
});
function validateInput(elm, e) {
// handle keydown event
if (e) {
// do not allow floating-point numbers, if it's not expected
if (!isFloat(elm.step)) {
if (e.key == ".") {
e.preventDefault();
}
}
}
// handle input event
else {
// do not allow leading zeros
while (elm.value.length > 1 && elm.value[0] === "0") {
elm.value = elm.value.toString().slice(1);
}
// input should be between min and max
if (elm.validity.rangeUnderflow) {
elm.value = elm.min;
} else if (elm.validity.rangeOverflow) {
elm.value = elm.max;
}
}
}
function isFloat(f) {
var f = parseFloat(f);
var floor = Math.floor(f);
var fraction = f - floor;
if (fraction > 0) {
return true;
}
return false;
}
<input type="number" id="inputBox" min="0" max="255" step="1" />
But the user can still modify the input field value programmatically. The user can enter the following values through the console to bypass the validation and these are invalid/unexpected values:
inputBox.value = "005";
inputBox.value = "2.5"
inputBox.value = "-05.5";
An ideal solution to this would be to call a function (e.g. validateProgrammaticInput()) if the user changes the field value using inputBox.value.
inputBox.value = -10; // magically call validateProgrammaticInput()
Note: I'm not using a form. There's no submit button. This will not be sent to a server. This is a client application. Value should be validated in real-time. If I want to modify the field value programmatically, I can trigger a custom event in my code to validate the input, but that's not the case. What I want is to validate the input, if the user enters it programmatically. So my use case is irrelevant to the problem. Thought I should point these out before a confusion.

you can trigger the event programmaticaly after changing the value like this
var inputBox = document.getElementById("inputBox");
inputBox.addEventListener("input", function () {
console.log("input");
// input should be between min and max
if (this.validity.rangeUnderflow) {
this.value = this.min;
}
else if (this.validity.rangeOverflow) {
this.value = this.max;
}
// do not allow leading zeros
while (this.value.length > 1 && this.value.toString()[0] === "0") {
this.value = this.value.toString().slice(1);
}
});
inputBox.addEventListener("keydown", function (e) {
// do not allow floating-point numbers, if it's not expected
if (!isFloat(this.step)) {
if (e.key == ".") {
e.preventDefault();
}
}
},false);
function change(){
inputBox.value = "005";
inputBox.dispatchEvent(new Event('input'));
}
function isFloat(n){
return Number(n) === n && n % 1 !== 0;
}
<input type="number" id="inputBox" min="0" max="255" step="1" />
<button onclick="change()">change</button>

So, to me, your event listeners aren't triggered at all because theyre not occurring. There's no "keydown" on the field when the values are changed programmatically, as no events are triggered in the DOM.
To me, I think you should wire some other event handler as well that's more "page level". In looking at the jQuery event categories (https://api.jquery.com/category/events/) what if you assigned these events to the page itself - on mouse x\y changing, on page enter\leave and focus\blur.
It may seem a little overboard to use all of these events, but this seems to be a unique case. To me, you never really trust user input, so I tend to recalculate\validate data when submit by the user, but for this scenario where the data isn't being submitted to you, I think triggering these items by some page level events rather than input specific events may get you over the hump...

Related

How to call methods on input of 'number' type?

I'm new to HTML and have an input with type=number:
<input type="number" min="1" value="1" id="amount-input" (click)="chooseStanding(standingspot.priceCategory)">
With (click), chooseStanding(standingspot.priceCategory) will be called every time the up or down button is clicked.
But is it possible to have different method calls based on which button was clicked? For example, if the down button was pressed a different method removeStanding(standingspot.priceCateegory) should be called and if the up button was pressed, chooseStanding(standingspot.priceCategory) should be called. I would really appreciate any help! :)
Similar to Dan's solution, but taking into consideration the exact difference between the previous and the next value.
Also, there is no need to store the previous value in a variable.
const onIncrement = () => console.log('INCREMENT');
const onDecrement = () => console.log('DECREMENT');
const onChange = value => console.log('CHANGE TO: ', value);
const onChangeNumber = event => {
const input = event.target;
const newValue = parseInt(input.value);
const oldValue = parseInt(input.getAttribute('old-value') || input.defaultValue) || 0;
input.setAttribute('old-value', input.value);
if (newValue === oldValue + 1)
onIncrement();
else
if (newValue === oldValue - 1)
onDecrement();
else
onChange(newValue);
}
<input type='number' onchange='onChangeNumber(event)' defaultValue="0"/>
You can store the number value and on change you compare the new input value to the old input value and from there you can determine which button was pressed.
var value = null;
var previousValue = null;
function chooseStanding() {
var input = document.getElementById("amount-input");
if (previousValue == null) {
previousValue = input.value;
}
previousValue = value;
value = input.value;
if (previousValue > value) {
// down button pressed
console.log("down");
}
else if (previousValue < value) {
// up button pressed
console.log("up");
}
}
<input type="number" min="1" value="1" id="amount-input" onchange="chooseStanding()">
No, this is not possible. And notice that the click event also fires when you click anywhere else on the input, not just on the buttons. A number input is really about entering numbers, you only should use the number value in your event handlers. If you want to execute some actions when clicking on buttons, don't use a number input but two <button> elements.

Ensure a positive integer number in input

I have an HTML input element for positive integer numbers. I need to evaluate this input field and ensure that only proper values are inserted.
function exampleFunction(event, element) {
// If event is not backspace and Not a Number
if (event.which != 8) {
//If the event is Not a Number
if (isNaN(String.fromCharCode(event.which))) {
// Cancels the event
event.preventDefault();
}
//If the length reached the limit
else {
var value = document.getElementById(element.id).value;
var maxLength = document.getElementById(element.id).maxLength;
var valueLength = document.getElementById(element.id).value.length;
if (valueLength >= maxLength) {
// Cancels the event
event.preventDefault();
} else {
// Convert the value to a number and back to string. This means leading 0 will be gone.
document.getElementById(element.id).value = Number(value);
}
}
}
};
<input id="exampleInput" type="number" value="0" min="0" step="1" maxlength="5" onkeypress="exampleFunction(event, this)">
purposes:
default value is 0
only numbers shall be accepted
no decimal value .,
no other characters +-e
the input can come from:
typing
copy
backspace and delete can also modify the value
length of input shall also be limited for 5 character length
leading 0 shall be eliminated after a proper new value
Problems:
the default value is 0 and leading zeros are not immediately deleted, only after the second number is typed
with ctrl+v .,+-e characters can be inserted
Question:
Is any better solution for my purposes?
If it is jQuery related, it is also acceptable.
Maybe I am not using the proper event. I tried also to handle the
input event but it is not possible to evaluate the input text.
I am not sure if I make this too complicated, or the solution would be much more complex than I think.
I suggest you to use .addEventListener() instead of the inline event handler.
So to the same input element, you can add more than one event. To do what you wish to do, there are three events implied:
keydown to prevent the not allowed keys
contextmenu for mouse pasting
input to parseInt the value
The below snippet is restricting the input to nubers only. No dot, minus sign, e or whatever except numbers are allowed.
Pasting can be done via [CTRL]+[v] or the mouse contextmenu. In both cases, I assume the previous value of the input should be squarely cleared.
I took the pasted negative numbers case in account using Math.abs().
// Get the element
let myInput = document.querySelector("#exampleInput")
// This event handler only allows numbers, backspace and [ctrl]+[v]
myInput.addEventListener("keydown", function(event) {
console.log("Key:", event.key)
// If this is to be a keyboard paste [CTRL]+[v],
// squarely clears the input value before the paste is done
if (event.ctrlKey && event.key === "v") {
console.log("keyboard paste")
this.value = ""
return;
}
// If the key is not backspace, but is NAN, it is not a number.
// In short, only a number OR a backspace is allowed at this point.
if (event.key !== "Backspace" && isNaN(event.key)) {
event.preventDefault();
console.log(" --------- Event prevented")
}
});
// This handler is for "mouse pastes"
// It squarely clears the input value before the paste is done
myInput.addEventListener("contextmenu", function(event) {
this.value = ""
})
// This handler fixes the value length and parses as a positive integer
myInput.addEventListener("input", function(event) {
console.log("Original value", this.value)
// Get the maxlength attribute value
var maxLength = parseInt(this.maxLength)
// ParseInt the value (will remove any leading zero) and ensure it is positive
// Then keep just the [maxlength] first characters.
var value = Math.abs(parseInt(this.value)).toString().slice(0, maxLength)
console.log("Fixed value", value)
this.value = value;
});
<input id="exampleInput" type="number" value="0" min="0" step="1" maxlength="5">
Here we go with a JQuery solution
Features:
Remove default "0" on focus.
Set maximum length to (5)
Allowed numeric content only and Backspace, Del, Home, End, Arrow-Left, Arrow-Right,
ctrl+v, ctrl+c, ctrl+a buttons.
Check if the copied text contains any numeric value and collect it and remove non-numeric values.
Check if pasted text length + current value length are meeting maximum length
$(document).ready(function() {
//Remove default "0" ONLY! when focus at the input.
$("#exampleInput").on('focus', function() {
var oldval = $("#exampleInput").val();
if (oldval < 1) {
$("#exampleInput").val("");
}
});
/* SET CTRL+V , CTRL+C funciton */
var ctrlprs = false,
ctrlk = 17,
mccmd = 91,
vk = 86,
ak = 65,
ck = 67;
$(document).keydown(function(e) {
if (e.keyCode == ctrlk || e.keyCode == mccmd) ctrlprs = true;
}).keyup(function(e) {
if (e.keyCode == ctrlk || e.keyCode == mccmd) ctrlprs = false;
});
//Listen to the input in keydown
$("#exampleInput").on('keydown', function(e) {
var txt = $("#exampleInput").val();
//exceptions for [b-space,end,home,left,right,del]
var keys = [8, 35, 36, 37, 39, 46];
var rgx = $.inArray(e.which, keys) < 0;
var cnvrt = String.fromCharCode(e.which);
/* allow CTRL + "a or c or v" */
if (ctrlprs && ((e.keyCode == ck) || (e.keyCode == ak) || (e.keyCode == vk))) {
} else if ((txt.length == 5) || (cnvrt.match(/[^0-9]/)) || (e.shiftKey)) {
if ((rgx)) {
e.preventDefault();
/* prevent all text except numbers, and set max input value length to (5) */
}
}
});
/*Bind a paste function to check if clipboard data met with requirements or not.*/
$("#exampleInput").on('paste', function(e) {
var oldl = $("#exampleInput").val();
var oldval = e.originalEvent.clipboardData.getData('text');
if (oldval.match(/[0-9]{1,5}$\d/g)) {} else {
//remove all non-numeric text from clipboard text.
var newvar = oldval.replace(/\D/g, "");
setTimeout(function() {
//check if ( clipboard[Numeric only] + input value ) length equals or less than (5).
var totlen = oldl.length + newvar.length;
if (newvar.length > 0 && totlen <= 5) {
$("#exampleInput").val(oldl + newvar);
} else {
//if total length is more than (5) keep the input value before paste.
console.log("total length is : " totlen);
$("#exampleInput").val(oldl);
}
}, 1);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="exampleInput" type="number" value="0" min="0" step="1" maxlength="5">

How can I prevent numeric inputs using VueJS

I need to create a validation that prevent the user from inputting numeric inputs on a textbox. I found some solution using a native javascript but it is not working on my side.
On my text box I have this trigger
v-on:keyup="preventNumericInput($event)">
And on my Vue I created a function on my class
preventNumericInput($event) {
console.log($event.keyCode); //will display the keyCode value
console.log($event.key); //will show the key value
var keyCode = ($event.keyCode ? $event.keyCode : $event.which);
if (keyCode > 47 && keyCode < 58) {
$event.preventDefault();
}
}
Can you help me with this?
As mentioned in my comment, keyup will be firing too late to prevent the value being entered into the input field. For example, think about holding a key down to enter the same value repeatedly; there is no key up.
Instead, usekeydown or keypress
<input #keypress="preventNumericInput">
Demo ~ http://jsfiddle.net/wadt08jm/1/
Input must be type number, otherwise isNaN won't work
<input type="number" :value="price" step="0.1" min="0" #input="onInput($event)" >
into input replace ',' by '.'
test if not number
if not number replace observable price by element.value
data () {
return { price: 0 }
},
methods: {
onInput (e: Event) {
const element = e.target as HTMLInputElement
const value = parseFloat(element.value === '' ? '0' : element.value.replace(',', '.'))
if (isNaN(value)) {
element.value = this.price.toString()
} else {
this.price = value
}
}
}

According to dropdown change on input keydown certain functionality should be done

There is one dropdown and inputbox. If Aadhar is selected in dropdown i am assigning keydown event for input box which takes numeric only. In case of PASSPORT i am changing keydown event which takes alphanumeric characters.
function changeDocumentType(pthis) {
//dropdown change
var htmlid = "#" + pthis.id;
var doctype = $(htmlid+':selected').val();
populateValidations(doctype,"docId");
}
function populateValidations(doctype,inputId){
$("#"+inputId).removeAttr("onkeydown");
$("#"+inputId).removeClass("onlyNumeric");
$("#"+inputId).removeClass("alphabetNumeric");
if(doctype === "1"){
//aadhar
$("#"+inputId).addClass("onlyNumeric");
$("#"+inputId).attr("onkeydown", "return inputOnlyNumberTablet(this,event,12)");
}
if(doctype === "2") {
//passport
$("#"+inputId).addClass("alphabetNumeric");
$("#"+inputId).attr("onkeydown", "return inputOnlyAlphaNumericTablet(this,event,10)");
}
}
function inputOnlyAlphaNumericTablet(pthis, event, length){
$('.alphabetNumeric').on('input', function(event) {
if (pthis.value.length <= parseInt(length, 10)) {
pthis.value = pthis.value.replace(/[^a-z0-9]/gi, '');
} else {
pthis.value = pthis.value.substr(0, pthis.value.length - 1);
}
});
}
}
function inputOnlyNumberTablet(pthis, event, length){
$('.onlyNumeric').on('input', function(event) {
if (pthis.value.length <= parseInt(length, 10)) {
pthis.value = pthis.value.replace(/[^0-9]/g, '');
} else {
pthis.value = pthis.value.substr(0, pthis.value.length - 1);
}
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="docId" type="text" value="" enabled="enabled" >
<select style="" value="" enabled="enabled" onchange="changeDocumentType(this)" id="DocumentListFile">
<option value="">Select</option>
<option value="1">Aadhar ID</option>
<option value="2">PassPort</option>
</select>
If once aadhar is selected for passport also it is taking only numeric input. This code is return for android device. Any solution??
Thanks.
You have to remove the other keydown listener before binding the new one else you get multiple listeners each time you perform your dropdown,
Simply removing the attribute from the element doesn't unbind the event.
This isn't a complete copy/paste answer. It's an example, to which you can tweak to your needs. I've just taken the part of your code that assigns the listener and changed it.
function populateValidations(doctype,inputId){
var inp = $("#"+inputId); // get this once. Easier if there is a name change etc
inp.unbind('keydown'); // unbind any keydown event that may exist
inp.removeClass("onlyNumeric");
inp.removeClass("alphabetNumeric");
if(doctype === "1"){
//aadhar
inp.addClass("onlyNumeric");
// add your keydown
inp.keydown(function(){ return inputOnlyNumberTablet(this,event,12);});
}
if(doctype === "2") {
//passport
inp.addClass("alphabetNumeric");
inp.keydown(function(){return inputOnlyAlphaNumericTablet(this,event,10);});
}
}

Javascript: How to read a hand held barcode scanner best?

I'd like to be able to scan barcodes via a hand held scanner and handle the results with Javascript.
A barcode-scanner works almost like a keyboard. It outputs the scanned/translated (barcode->number) data raw (right?). Actually I just need to catch the output and proceed. But how?
Here's some pseudocode I'd like to make work:
$(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>");
});
Any ideas (frameworks, plugins, snippets)?
Any barcode-scanner (hardware) recommendation?
I found this and this good questions but I'd like to get more information about the handling. Just to focus a textarea may be not enough in my case.
Your pseudo code won't work, because you don't have access to the scanner to catch events like scanButtonDown. Your only option is a HID scanner, which behaves exactly like a keyboard. To differentiate scanner input from keyboard input you have two options: Timer-based or prefix-based.
Timer-based
The scanner is likely to input characters much quicker than a user can (sensibly) with a keyboard. Calculate how quickly keystrokes are being received and buffer fast input into a variable to pass to your getProductsId function. #Vitall wrote a reusable jQuery solution for catching barcode scanner input, you would just need to catch the onbarcodescanned event.
Prefix-based
Most scanners can be configured to prefix all scanned data. You can use the prefix to start intercepting all input and once you've got your barcode you stop intercepting input.
Full disclosure: I work as a consultant to Socket Mobile, Inc. who make handheld scanners.
After a lot of research and testing, what worked the best for me was to capture input from a barcode scanner without focusing a form input. Listen to the keydown and textInput events.
The textInput event acts like a paste event. It has then entire barcode data. In my case I am looking for UPC barcodes. The e.preventDefault() prevents the barcode data from being inserted into a form input:
document.addEventListener('textInput', function (e){
if(e.data.length >= 6){
console.log('IR scan textInput', e.data);
e.preventDefault();
}
});
I have tested this on Android 4.4 and 7.0 with a CipherLab IR scanner.
Example for listening to the keydown event. In my case I am able to assume that as long as a form input is not focused, the user is scanning a barcode.
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);
}
}
});
Of course, rather than checking the length of the string to determine a scan, you can listen for the e.keyCode === 13 in the keydown event listener.
Not all IR scanners will trigger the textInput event. If your device does not, then you can check to see if it is emitting something similar with:
monitorEvents(document.body);
Found this monitoring trick here: How do you log all events fired by an element in jQuery?
I'm little late but I made this work around based in some answers here.
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
}
});
A barcode-scanner works almost like a keyboard.
It depends on the model. Every one that I've used works exactly like a keyboard (at least as far as the computer is concerned)
It outputs the scanned/translated (barcode->number) data raw (right?).
It outputs keycodes.
$(document).on("scanButtonDown"
You probably want keypress, not scanButtonDown.
Look at the event object to determine the "key" that was pressed.
To determine when the entire code has been scanned, you might get an "end of data" key (possibly a space or a return) or you might have to just count how many characters are being input.
Here is working fine.
It's working when input has focus and input hasn't focus
on_scanner() // init function
function on_scanner() {
let is_event = false; // for check just one event declaration
let input = document.getElementById("scanner");
input.addEventListener("focus", function () {
if (!is_event) {
is_event = true;
input.addEventListener("keypress", function (e) {
setTimeout(function () {
if (e.keyCode == 13) {
scanner(input.value); // use value as you need
input.select();
}
}, 500)
})
}
});
document.addEventListener("keypress", function (e) {
if (e.target.tagName !== "INPUT") {
input.focus();
}
});
}
function scanner(value) {
if (value == '') return;
console.log(value)
}
HTML
<input type="text" id="scanner" placeholder="scanner">
Tried all the solutions, but not worked as expected. I found very easiest solution onscan.js I have application using angular 8.
Very simple and good implementation.
For angular 8, I followed steps:
1.npm install onscan.js --save
2.open angular.json, add one entry to script array as "node_modules/onscan.js/onscan.min.js"
3.In component class, implement interface 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);
},
});
}
Best thing is scanned text appears into focued textbox element
Hope this help.
I wanted to share this topic using React too, as I struggled a lot with it.
I think most of the barcode scanners, such as Hanz Herdel said, terminate with ENTER. In my case, I found easier to wrap the input in a form and catch the submission event, prevent default and retrieve the value of the input.
I preferred this type of approach so to handle any type of barcode length, instead to check the length of it.
Here's how I handled it in 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>
)
}
This is an extension to the answer given by Hanz Herdel incase you are using one of the PosX scanners or any other scanner that are capable of adding a special symbol to the beginning of the characters. In this case, the tilde (~) symbol:
let barcode = "";
let reading = false;
document.addEventListener("keydown", e => {
//console.log(e.key);
if (e.key == 'Enter') {
if (barcode.length == 17) {
if (barcode.charAt(0) == '~') {
console.log(barcode);
barcode = "";
}
}
}
else {
if (e.key != 'Shift') {
barcode += e.key;
}
}
if (!reading) {
reading = true;
setTimeout( () => {
barcode = "";
reading = false;
}, 200);
}
}, true)
You can change the barcode length and the timeout speed to your liking but this worked perfect for me.
Vue 2 implementation (i think vuejs's syntax is similar to angular):
BarcodeScanner.vue component code is here:
<template>
<input type="hidden" name="_barcode" v-model="finalCode" />
</template>
<script>
export default {
props: {
onSuccess: {
type: Function,
required: true
},
minLength: {
type: Number,
default: () => 10
}
},
data() {
return {
code: "",
finalCode: "",
fromScanner: false,
reading: false
};
},
mounted() {
document.addEventListener("keypress", this.documentKeyboardListener);
},
destroyed() {
document.removeEventListener("keypress", this.documentKeyboardListener);
},
methods: {
documentKeyboardListener(e) {
if (e.target.nodeName !== 'BODY') return;
if (e.code === "Enter") {
if (this.reading && this.code.length > this.minLength) {
if (this.onSuccess)
this.onSuccess(this.code);
this.finalCode = this.code;
this.code = "";
this.fromScanner = true;
}
} else {
this.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 (!this.reading) {
this.reading = true;
setTimeout(() => {
this.code = "";
this.reading = false;
this.fromScanner = false;
}, 200); //200 works fine for me but you can adjust it
}
},
},
};
</script>
You can invoke the component anywhere:
...
<barcode-scanner onSuccess="yourListener"/>
...
(Js scanner code is taken from Hanz Herdel)
I've just started working on a plugin that handles barcode scanning and credit card scanning (built on jQuery):
https://github.com/ericuldall/jquery-pos
Simple implementation:
$(function(){
$(document).pos();
$(document).on('scan.pos.barcode', function(event){
var barcode = event.code;
//handle your code here....
});
});
So far this plugin is only tested with one type of scanner and codes containing only digits, but if you have further requirements that aren't working with it, I'd be happy to adapt it to your needs. Please check out the github page and give it a whirl. Contributions are encouraged.
E
var txt = "";
function selectBarcode() {
if (txt != $("#focus").val()) {
setTimeout('use_rfid()', 1000);
txt = $("#focus").val();
}
$("#focus").select();
setTimeout('selectBarcode()', 1000);
}
$(document).ready(function () {
setTimeout(selectBarcode(),1000);
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="text" name="tag" id="focus" placeholder="Use handheld RFID scanner">
Needs hardening but this routine, which counts on scanned data being sent in under 100ms, is working in production. Thanks to #jfbloom22 and other answers for inspiration and reminding me of monitorEvents.
It appears scanners need to be set to send "HID Keyboard"-type data(?) and be set to terminate with "Enter".
Although is purely JavaScript logic, was written in TypeScript app for a PCF (Power Apps Component Framework) project that allows the app to accept scan data without the need to focus on an input box. Globals were used as a convenience.
public Scan(evt: Event): void {
const e:KeyboardEvent = evt as KeyboardEvent;
const timeDiff = e.timeStamp - CheckInPCF.LastTimeStamp;
CheckInPCF.LastTimeStamp = e.timeStamp; //"global"
//console.log(e.key + ': ' + timeDiff);
if (timeDiff < 100) {
if (e.key == 'Enter') {
//Assemble complete scan text
CheckInPCF.ScanText = CheckInPCF.FirstCharacterCandidate + CheckInPCF.ScanText; //.replace('\u000D','');
//console.log('finished: ' + CheckInPCF.ScanText);
CheckInPCF._this._notifyOutputChanged(); //Power Apps related
}
else {
CheckInPCF.ScanText += e.key;
}
}
else {
CheckInPCF.ScanText = '';
CheckInPCF.FirstCharacterCandidate = e.key;
}
}
This code works fine for me, you can try it
var barcode = '';
var interval;
document.addEventListener('keydown', function(evt) {
if (evt.code === 'F12'){
evt.preventDefault();
}
if (interval){
clearInterval(interval);
}
if (evt.code == 'Enter') {
if (barcode){
$('#barcode').val(barcode);
console.log(barcode);
}
barcode = '';
return;
}
if (evt.key != 'Shift'){
barcode += evt.key;
}
interval = setInterval(() => barcode = '', 20);
});

Categories