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