I am developing a web application that needs to scan barcode to input value in textbox of some forms. Because the web application will be accessed from tablet and smartphones, I want to make use of device camera for reading barcode. And because it is not just one page that need to scan barcode, i want to seperate the scanning page. To summarize it, here is what i want to do;
1. From the main page, which is having a textbox that needs to be input from barcode, i click button to open the barcode-reader page.
2. The barcode reader page is opening in a new window or tab, and access device camera to read the barcode.
3. After reading the barcode, it will send the result to the main page textbox and close itself.
Here is the workaround i did. I am using Quagga.js for reding the barcode.
1. Quaggajs example
2. window open method
1. From the main page, which is having a textbox that needs to be input from barcode, i click button to open the barcode-reader page.
2. The barcode reader page is opening in a new window or tab, and access device camera to read the barcode.
3. After reading the barcode, it will send the result to the main page textbox and close itself.
Here is the workaround i did. I am using Quagga.js for reding the barcode.
Main page
index.html
<html> <head> <title>Barcode Text</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> function openReader(){ window.open("./BarcodeReader.html"); } </script> </head> <body> <input type="text" id="barcode-text"> <button type="button" onclick="openReader()">Scan barcode</button> </body> </html>
Subpage (Barcode-reader page)
BarcodeReader.html
<html> <head> <title>Barcode Reader</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="js/jquery-1.11.3.js" type="text/javascript"></script> <script src="js/quagga.js" type="text/javascript"></script> <script src="js/BarcodeReader.js" type="text/javascript"></script> <meta name="viewport" content="width=device-width; initial-scale=1.0" /> </head> <body style="text-align: center;"> <div id="result_strip"> <ul class="thumbnails"></ul> <ul class="collector"></ul> </div> <div id="interactive" class="viewport"></div> </body> </html>
Basically, I use the javascript example from Quaggajs examples as is. I just modified it in the part where barcode detected to send the result to window opener. See the code in the last lines.
$(function() { var resultCollector = Quagga.ResultCollector.create({ capture: true, capacity: 20, blacklist: [{code: "2167361334", format: "i2of5"}], filter: function(codeResult) { // only store results which match this constraint // e.g.: codeResult return true; } }); var App = { init : function() { var self = this; Quagga.init(this.state, function(err) { if (err) { return self.handleError(err); } Quagga.registerResultCollector(resultCollector); App.attachListeners(); Quagga.start(); }); }, handleError: function(err) { console.log(err); }, attachListeners: function() { var self = this; $(".controls").on("click", "button.stop", function(e) { e.preventDefault(); Quagga.stop(); self._printCollectedResults(); }); $(".controls .reader-config-group").on("change", "input, select", function(e) { e.preventDefault(); var $target = $(e.target), value = $target.attr("type") === "checkbox" ? $target.prop("checked") : $target.val(), name = $target.attr("name"), state = self._convertNameToState(name); console.log("Value of "+ state + " changed to " + value); self.setState(state, value); }); }, _printCollectedResults: function() { var results = resultCollector.getResults(), $ul = $("#result_strip ul.collector"); results.forEach(function(result) { var $li = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>'); $li.find("img").attr("src", result.frame); $li.find("h4.code").html(result.codeResult.code + " (" + result.codeResult.format + ")"); $ul.prepend($li); }); }, _accessByPath: function(obj, path, val) { var parts = path.split('.'), depth = parts.length, setter = (typeof val !== "undefined") ? true : false; return parts.reduce(function(o, key, i) { if (setter && (i + 1) === depth) { o[key] = val; } return key in o ? o[key] : {}; }, obj); }, _convertNameToState: function(name) { return name.replace("_", ".").split("-").reduce(function(result, value) { return result + value.charAt(0).toUpperCase() + value.substring(1); }); }, detachListeners: function() { $(".controls").off("click", "button.stop"); $(".controls .reader-config-group").off("change", "input, select"); }, setState: function(path, value) { var self = this; if (typeof self._accessByPath(self.inputMapper, path) === "function") { value = self._accessByPath(self.inputMapper, path)(value); } self._accessByPath(self.state, path, value); console.log(JSON.stringify(self.state)); App.detachListeners(); Quagga.stop(); App.init(); }, inputMapper: { inputStream: { constraints: function(value){ var values = value.split('x'); return { width: parseInt(values[0]), height: parseInt(values[1]), facing: "environment" } } }, numOfWorkers: function(value) { return parseInt(value); }, decoder: { readers: function(value) { return [value + "_reader"]; } } }, state: { inputStream: { type : "LiveStream", constraints: { width: 640, height: 480, facing: "user" //"environment" // or user } }, locator: { patchSize: "medium", halfSample: true }, numOfWorkers: 4, decoder: { readers : ["code_39_reader"] }, locate: true }, lastResult : null }; App.init(); Quagga.onProcessed(function(result) { var drawingCtx = Quagga.canvas.ctx.overlay, 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 (result.codeResult && result.codeResult.code) { Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3}); } } }); Quagga.onDetected(function(result) { var code = result.codeResult.code; if (App.lastResult !== code) { App.lastResult = code; //This part is the important one to give result back to the main page //stop the script and close sub window. window.opener.document.getElementsById("barcode-text").value = code; Quagga.stop(); window.close(); } }); });
Referrence
2. window open method
Hi.. its not working. Nothing happen after new tabs open. Any solution?
ReplyDeletedoes not work
ReplyDelete