6 This page can be used to read a barcode directly from the website
7 using the device's camera. If a barcode is successfully read, the
8 page will return to the provided return url with a query parameter
9 set to the URI encoded contents of the read barcode.
11 Usage: /barcode/read?return=/breeders/seedlot/maintenance¶m=barcode
12 This will start the barcode reader and when a barcode is found, change
13 the location of the browser to:
14 /breeders/seedlot/maintenance?barcode={{contents}}
16 The javascript qr code reader used: https://github.com/cozmo/jsQR
17 Code based on demo: https://cozmo.github.io/jsQR/
20 <& /util/import_javascript.mas, classes => [ 'bootstrap_min.js', 'jquery', 'jsqr' ] &>
22 <& /page/page_title.mas, title => 'Barcode Reader' &>
24 <div class="panel panel-default">
25 <div class="panel-heading">Scan a Barcode<span id="panel-heading-return"></span></div>
26 <div class="panel-body" style="text-align: center">
27 <div id="loadingMessage">Starting...</div>
28 <canvas id="canvas" hidden></canvas>
30 <div class="panel-footer">Scanning for Barcode...</div>
33 <script type="text/javascript">
35 let RETURN_URL = undefined;
36 let RETURN_PARAM = undefined;
38 jQuery(document).ready(function() {
40 // Parse the query arguments
43 // Start the Barcode Reader
50 * Parse the query params for the return url and param
52 function parseArgs() {
53 const urlSearchParams = new URLSearchParams(window.location.search);
54 if ( urlSearchParams.has('return') ) {
55 RETURN_URL = decodeURIComponent(urlSearchParams.get('return'));
56 jQuery("#panel-heading-return").html(" to return to <a href='" + RETURN_URL + "'>" + RETURN_URL + "</a>");
58 RETURN_PARAM = urlSearchParams.get('param');
63 * Start the Barcode Reader
64 * - Start the camera feed
65 * - Start processing the images for a barcode
66 * - Call processCode(data) when a barcode has been found
68 function startReader() {
69 var video = document.createElement("video");
70 var canvasElement = document.getElementById("canvas");
71 var canvas = canvasElement.getContext("2d");
72 var loadingMessage = document.getElementById("loadingMessage");
73 loadingMessage.innerHTML = "<strong>Unable to access video stream</strong><br />Please make sure you have a webcam enabled and permissions have been granted for this site</p>";
75 // Use facingMode: environment to attemt to get the front camera on phones
76 navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } }).then(function(stream) {
77 video.srcObject = stream;
78 video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
80 requestAnimationFrame(tick);
84 loadingMessage.innerText = "Loading video...";
85 if (video.readyState === video.HAVE_ENOUGH_DATA) {
86 loadingMessage.hidden = true;
87 canvasElement.hidden = false;
89 canvasElement.height = video.videoHeight;
90 canvasElement.width = video.videoWidth;
91 canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
92 var imageData = canvas.getImageData(0, 0, canvasElement.width, canvasElement.height);
93 var code = jsQR(imageData.data, imageData.width, imageData.height, {
94 inversionAttempts: "dontInvert",
97 drawLine(code.location.topLeftCorner, code.location.topRightCorner, "#FF3B58");
98 drawLine(code.location.topRightCorner, code.location.bottomRightCorner, "#FF3B58");
99 drawLine(code.location.bottomRightCorner, code.location.bottomLeftCorner, "#FF3B58");
100 drawLine(code.location.bottomLeftCorner, code.location.topLeftCorner, "#FF3B58");
101 processCode(code.data);
104 requestAnimationFrame(tick);
107 function drawLine(begin, end, color) {
109 canvas.moveTo(begin.x, begin.y);
110 canvas.lineTo(end.x, end.y);
111 canvas.lineWidth = 4;
112 canvas.strokeStyle = color;
119 * Stop the camera feed
121 function stopReader() {
123 var stream = video.srcObject;
124 var tracks = stream.getTracks();
126 tracks.forEach(function(track) { track.stop(); });
127 video.srcObject = null;
128 canvas.clearRect(0, 0, canvasElement.width, canvasElement.height);
129 cancelAnimationFrame(animFrameId);
135 * Process the QR code data
136 * - If return and param args are set, return to the provided url
137 * @param {string} data QR Code data
139 function processCode(data) {
140 jQuery(".panel-footer").html("<strong>Barcode Found:</strong> " + data);
141 if ( data && data !== "" && RETURN_URL && RETURN_URL !== "" && RETURN_PARAM && RETURN_PARAM !== "" ) {
142 let q = RETURN_URL.includes('?') ? '&' : '?';
143 window.location = RETURN_URL + q + RETURN_PARAM + '=' + encodeURIComponent(data);