Sample barcode reader I made to learn JavaScript
Resources:
- JS barcode scanner library: https://github.com/serratus/quaggaJS
- Live examples: https://serratus.github.io/quaggaJS/examples/
- Sample code:
Sample barcode reader I made to learn JavaScript
Resources:
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Demi Barcode</title> | |
| <!-- Firefox's console complains if this isn't provided --> | |
| <meta http-equiv="content-type" content="text/html; charset=utf-8" /> | |
| <!-- This makes things bigger on mobile devices --> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <!-- Should be a separate file, but I was too lazy --> | |
| <style> | |
| /* The window that appears once scan is clicked */ | |
| /* Couldn't figure out how to resize the video+canvas properly; maybe flexbox would help */ | |
| #cameraView { | |
| position: absolute; | |
| background: gray; | |
| left: 20vw; | |
| top: 20vh; | |
| width: 60vw; | |
| height: 60vh; | |
| } | |
| #viewport { | |
| position: relative; | |
| height: 80%; | |
| } | |
| #viewport canvas, #viewport video { | |
| position: absolute; /* draw the canvas on top of the video */ | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| #cancelButton { | |
| height: 20%; | |
| width: 100%; | |
| padding: 6%px; | |
| } | |
| /* The smaller image that shows a successfully scanned image */ | |
| #thumbnailView { | |
| position: relative; | |
| } | |
| #thumbnailView img, #thumbnailView canvas { | |
| width: 150px; | |
| height: 100px; | |
| } | |
| #thumbnailView canvas { | |
| position: absolute; /* draw the canvas on top of the image */ | |
| left: 0; | |
| top: 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- The barcode scanner library --> | |
| <script src="//serratus.github.io/quaggaJS/examples/js/quagga.min.js" type="text/javascript"></script> | |
| <!-- The $("..") thingy to easily find and make elements in javascript --> | |
| <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript"></script> | |
| <!-- This page's code --> | |
| <script src="//demi.ro/barcode.js" type="text/javascript"></script> | |
| <p>Hi! Please give me a barcode image!</p> | |
| <form action="//tcl.demi.ro/cgi-bin/barcode.tcl"> | |
| <ul> | |
| <li> | |
| <div> | |
| <span>Code:</span> | |
| <input name="mybar" class="mybar" /> | |
| <button id="scanButton" type="button">Scan</button> | |
| </div> | |
| <div id="thumbnailView" style="display: none"> | |
| <img id="decodedImage"></img> | |
| <canvas id="decodedOverlay" class="drawingArea"></canvas> | |
| </div> | |
| </li> | |
| <li> | |
| <span>Car:</span> | |
| <select name="car" id="cars"> | |
| <option value="volvo">Volvo</option> | |
| <option value="saab">Saab</option> | |
| <option value="opel">Opel</option> | |
| <option value="audi">Audi</option> | |
| </select> | |
| </li> | |
| </ul> | |
| <input type="submit" class="submit" style="display: none" /> | |
| </form> | |
| <!-- Shown in case there's an error starting the camera --> | |
| <div class="error" style="display: none"></div> | |
| <!-- Shown when scanning --> | |
| <div id="cameraView" style="display: none"> | |
| <div id="viewport"></div> | |
| <div><button id="cancelButton">Cancel</button></div> | |
| </div> | |
| </body> | |
| </html> |
| $(document).ready(function(){ | |
| function startQuaggaScanner() { | |
| Quagga.init({ | |
| inputStream : { | |
| name: "Live", | |
| type: "LiveStream", | |
| target: document.querySelector('#viewport') | |
| }, | |
| decoder: { | |
| readers: [ | |
| "ean_reader", | |
| //"ean_8_reader", | |
| //"code_39_reader", | |
| //"code_39_vin_reader", | |
| //"codabar_reader", | |
| //"upc_reader", | |
| //"upc_e_reader", | |
| //"i2of5_reader", | |
| //"2of5_reader", | |
| //"code_93_reader" | |
| ], | |
| // patchSize: "x-large", // x-small, small, medium, large, x-large | |
| }, | |
| }, function(err) { | |
| if (err) { | |
| $("div.error") | |
| .text(err.toString()) | |
| .show(); | |
| console.log(err); | |
| return; | |
| } | |
| // Camera started, ready to begin searching for codes. | |
| Quagga.start(); | |
| }); | |
| } | |
| $("#scanButton").click(function() { | |
| startQuaggaScanner(); | |
| $("#cameraView").show(); | |
| }); | |
| $("#cancelButton").click(function() { | |
| Quagga.stop(); | |
| $("#cameraView").hide(); | |
| }); | |
| // When a barcode is detected, store it in a thumbnail and its code in an input | |
| Quagga.onDetected(function(result) { | |
| // Put the detected code into the html form | |
| $("input.mybar").val(result.codeResult.code); | |
| $("input.submit").show(); | |
| // Copy the image to thumbnail's img element | |
| const image = Quagga.canvas.dom.image; | |
| $("#decodedImage").attr("src", image.toDataURL()); | |
| // Copy the bounding boxes to the thumbnail's overlay canvas | |
| const overlay = Quagga.canvas.dom.overlay; | |
| const decOverlay = $("#decodedOverlay")[0]; | |
| // Clear the canvas in case the user scanned a second time | |
| decOverlay.getContext('2d').clearRect( | |
| 0, 0, decOverlay.width, decOverlay.height | |
| ); | |
| decOverlay.getContext('2d').drawImage( | |
| overlay, | |
| 0, 0, overlay.width, overlay.height, | |
| 0, 0, decOverlay.width, decOverlay.height | |
| ); | |
| // Stop scanning and stop the camera | |
| Quagga.stop(); | |
| $("#cameraView").hide(); | |
| $("#thumbnailView").show(); | |
| }); | |
| // Every time a potential barcode area is detected, draw a box around it | |
| Quagga.onProcessed(function(result) { | |
| var drawingCtx = Quagga.canvas.ctx.overlay; | |
| var drawingCanvas = Quagga.canvas.dom.overlay; | |
| if (result) { | |
| if (result.boxes) { | |
| drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height"))); | |
| result.boxes.filter(function (box) { | |
| return box !== result.box; | |
| }).forEach(function (box) { | |
| Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2}); | |
| }); | |
| } | |
| if (result.box) { | |
| Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2}); | |
| } | |
| // If a barcode was successfully decoded as well, draw a red line through it | |
| if (result.codeResult && result.codeResult.code) { | |
| Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3}); | |
| } | |
| } | |
| }); | |
| }); |
| #!/bin/tclsh | |
| package require cgi | |
| # Show the query args and show errors on the page | |
| cgi_debug -on | |
| # Display page elements only once the whole code was executed with no errors | |
| # Otherwise displays just an error message | |
| cgi_eval { | |
| # Parse query args | |
| cgi_input | |
| # Try to import query args into TCL variables | |
| if { [catch {cgi_import mybar}] || [catch {cgi_import car}] } { | |
| cgi_redirect "https://demi.ro/barcode.html" | |
| cgi_p "No barcode given! Redirecting..." | |
| } else { | |
| html { | |
| head { title "Demi-barcode" } | |
| cgi_body { | |
| cgi_p "Thanks! The bar code was: $mybar" | |
| cgi_p "And the car was: $car" | |
| } | |
| } | |
| } | |
| } |