简体   繁体   中英

Javascript: Hidden Input Barcode Scanner

Here's my current setup: I have a barcode scanner in keyboard mode. I am trying to scan to a hidden, out of focus input. The barcode I am trying to read is as follows: asterisk [barcode-info] asterisk and pastes as |[barcode-info]. (Stackoverflow wouldn't allow me to just place asterisks, but that is what the asterisk represents.)

<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>

I haven't been able to figure out how, but when a barcode input is made, I want Javascript to capture it and update the "barcode-input" hidden input, which will then submit itself to the server. I already have the server side figured out, just not sure how to get the hidden input from JS (not Jquery).

Someone recommended trying to use a paste event listener, but it simply didn't seem to capture the input at all. Scanner DOES work, as I can input into type="text" when it is in focus.

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 = '';
        }
    });

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...

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, ie 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>

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.

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;" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM