0

Here's my current setup: I have a barcode scanner in keyboard mode. I am trying to scan to a hidden and out of focus input. The barcode I am trying to read is as follows: asterisk [barcode-info] asterisk.

<form method="post">
  <input type="hidden" name="action" value="barcode-scan"/>
  <input type="hidden" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" />
</form>

When a barcode input is made, Javascript should capture it and update the "barcode-input" hidden input, which will then submit itself to the server.

Someone recommended trying to use a paste event listener, but it simply didn't seem to capture the input at all.

Update: because of wonderful suggestions below, I've been able to get the input working! The form will test to see if two specific inputs follow each other, then it will execute the next function. Otherwise, it will erase any information contained in the log const. Ultimately, yes, I got this working correctly!

document.addEventListener('keyup', function(e){
        const log = document.getElementById('barcode-input');
        log.textContent += ' ' + e.code;
        document.getElementById('barcode-input').value = log.textContent;

        if (log.textContent.startsWith(' ShiftLeft')) {

            if (log.textContent.startsWith(' ShiftLeft Backslash')) {
            document.getElementById('barcode-input').form.submit();
            console.log('e.code, submit barcode info');
            }
        }

        else {
            log.textContent = '';
            document.getElementById('barcode-input').value = '';
        }
    });
Scott Shaffer
  • 29
  • 1
  • 7

4 Answers4

2

Without an input[type="text"] element on the screen, you will need to capture the keyboard input manually. Something along the lines of:

document.addEventListener('keydown', (ev) => {
  if (ev.ctrlKey || ev.altKey) return;  // Ignore command-like keys
  if (ev.key == 'Enter') {
    // ...submit the content here...
  } else if (ev.key == 'Space') { // I think IE needs this
    document.getElementById('barcode-input').value += ' ';
  } else if (ev.key.length == 1) { // A character not a key like F12 or Backspace
    document.getElementById('barcode-input').value += ev.key;
  }
});

That should get you most of the way...

Mark Warren
  • 1,321
  • 1
  • 7
  • 4
0

Alternatively, rather than looking for events on the input or values of the input (*'s), define an event on the value and use the input event to simply set the value.

Once input has stopped, be it 1 second (or most likely much less) then fire off the form.

If you have to place the cursor into input, then scan. your prob only option is to use autofocus attribute and hide the input as you cant focus a hidden element, though you also cant focus multiple so keep that in mind if you're looking to scan into multiple inputs, then you will have to show the inputs, no way around it.

For example

let elm = document.querySelector('input[name="barcode-input"]')

// watcher on the value, after 1 second, it invokes an event, i.e post form
let timer = 0
Object.defineProperty(window, 'barcode', {
  get: function () { return this.value },
  set: function (value) {
    clearTimeout(timer)
    this.value = value
    timer = setTimeout(() => {
      console.log('Post form')
    }, 1000) // do some tests, tweak if much less then 1 second to input the value 
  }
})

// it should trigger input even if its a keyboard
elm.addEventListener("input", e => barcode = e.target.value)

// ignore, below this line..

// set a value of barcode at intervals, only when its stopped entering (>1 second), then will it fire the callback
let i = 0
let t = setInterval(() => {
  barcode = (barcode || '')+"X"
  if (i >= 40) clearInterval(t)
  i++
}, 100)

// ignore... grab value from hidden input, put in #current
setInterval(() => document.querySelector('#current').innerHTML = barcode, 1000)
<input type="text" name="barcode-input" autofocus style="display:none" />

<div id="current"></div>
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
0

Here's demonstrator using keypress that scans the incoming key stream for *[ and captures the barcode until it sees ]*. Then it sends the code to the server. Although I've reproduced the form in your HTML, the code here doesn't use it.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Working...
<form method="post">
    <input type="hidden" name="action" value="barcode-scan"/>
    <input type="hidden" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" />
</form>
<p id="response"></p>
<script>
    (function(){
        "use strict";
        const bcAst = '*';
        const bcLeft = '[' ;
        const bcRight = ']';

        let barcodeIncoming = false;
        let lastChar = 0;
        let barcode = '';

        document.addEventListener('keypress', function(e){

            function sendCode(barcode) {
                console.log(barcode);
                let fd = new FormData();
                fd.append('barcode', barcode);
                fetch('myFile.php', {
                    method: 'POST',
                    body: fd
                })
                .then(resp=>{
                    resp.text().then(txt=>{document.getElementById('response').innerText = txt;})
                });
            }

            console.log(e.key);
            switch (e.key) {
                case bcAst:
                    if (barcodeIncoming && (lastChar === bcRight)) {
                        barcodeIncoming = false;
                        sendCode(barcode);
                    }
                    break;
                case (bcLeft):
                    if (lastChar === bcAst) {
                        barcodeIncoming = true;
                        barcode = '';
                    }
                    break;
                case (bcRight):
                    break;
                default:
                    barcode += (barcodeIncoming)?e.key:'';
                    break;

            }
            lastChar = e.key;

        });
    })();
</script>
</body>
</html>

The current server file is very rudimetary, but serves the purpose here:

<?php
if (isset($_POST['barcode'])) {
    echo "Your barcode is {$_POST['barcode']}";
} else {
    echo "No barcode found";
}

Note - this has had only basic testing. You'll want to improve its resilience against possible collisions with similar data in the key stream.

-1

transfrom

<input type="hidden" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" />

in

<input type="test" name="barcode-input" value="" id="barcode-input" onchange="this.form.submit()" style="display:none;" />
remiok
  • 86
  • 3
  • How does changing the input type to some unsupported value help? If you meant to change it to `type="text"` you've missed the point of the question. – Tangentially Perpendicular Apr 15 '21 at 22:19
  • if the value works with the type = text as you say. in the past I have used the style = "display: none;" to not show the field but the value is there – remiok Apr 15 '21 at 22:25
  • I think he was trying to go for type="text", and he also added display:none as a style tag. That being said, I would still need to capture the input, and the change the value of the input field... And then deal with the fact that it is now a physical element on the page that needs to be arranged in such a way that it doesn't interfere with anything else. – Scott Shaffer Apr 15 '21 at 22:25
  • sorry then I didn't understand, I think @mark-warren answered you better :-) – remiok Apr 15 '21 at 22:38
  • I missed the `display:none`. This is why it pays to add an explanation of what you're suggesting rather than just dumping a code snippet. Nevertheless, there are other issues with this. – Tangentially Perpendicular Apr 15 '21 at 23:12