Fixed Events; Added example for multiple types of barcodes

feature/109
Christoph Oberhofer 9 years ago
parent be70d72e0b
commit 2f2ed46cf3

3166
dist/quagga.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -11,7 +11,7 @@
font-style: normal; font-style: normal;
} }
[class^="icon-"], [class*=" icon-"] { [class^="icon-"]:before, [class*=" icon-"]:before {
/* use !important to prevent issues with browser extensions that change fonts */ /* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important; font-family: 'icomoon' !important;
speak: none; speak: none;

@ -60,6 +60,7 @@
margin: -1rem; margin: -1rem;
border-radius: 2rem; border-radius: 2rem;
z-index: 100; z-index: 100;
box-sizing: content-box;
} }
.overlay__content video { .overlay__content video {
@ -223,13 +224,13 @@ header .headline {
} }
/* line 34, ../sass/styles.scss */ /* line 34, ../sass/styles.scss */
header .headline h1 { header .headline h1 {
color: #FFDD69;
font-size: 3em; font-size: 3em;
margin-bottom: 0; margin-bottom: 0;
} }
/* line 39, ../sass/styles.scss */ /* line 39, ../sass/styles.scss */
header .headline h2 { .headline h2 {
margin-top: 0.2em; margin-top: 0.2em;
color: #FFDD69;
} }
/* line 45, ../sass/styles.scss */ /* line 45, ../sass/styles.scss */
@ -244,8 +245,7 @@ footer {
} }
/* line 51, ../sass/styles.scss */ /* line 51, ../sass/styles.scss */
#container { .container {
max-width: 640px;
margin: 20px auto; margin: 20px auto;
padding: 10px; padding: 10px;
} }

@ -70,17 +70,19 @@ var App = {
}.bind(this)); }.bind(this));
}, },
attachListeners: function() { attachListeners: function() {
var self = this; var self = this,
document.querySelector('.input-field input + .button.scan') button = document.querySelector('.input-field input + .button.scan'),
.addEventListener("click", function onClick(e) { fileInput = document.querySelector('.input-field input[type=file]');
button.addEventListener("click", function onClick(e) {
e.preventDefault(); e.preventDefault();
e.target.removeEventListener("click", onClick); button.removeEventListener("click", onClick);
document.querySelector('.input-field input[type=file]').click(); document.querySelector('.input-field input[type=file]').click();
}); });
document.querySelector('.input-field input[type=file]')
.addEventListener("change", function onChange(e) { fileInput.addEventListener("change", function onChange(e) {
e.preventDefault(); e.preventDefault();
e.target.removeEventListener("change", onChange); fileInput.removeEventListener("change", onChange);
if (e.target.files && e.target.files.length) { if (e.target.files && e.target.files.length) {
self.decode(URL.createObjectURL(e.target.files[0])); self.decode(URL.createObjectURL(e.target.files[0]));
} }

@ -21,17 +21,19 @@ var App = {
}.bind(this)); }.bind(this));
}, },
attachListeners: function() { attachListeners: function() {
var self = this; var self = this,
document.querySelector('.input-field input + .button.scan') button = document.querySelector('.input-field input + .button.scan'),
.addEventListener("click", function onClick(e) { fileInput = document.querySelector('.input-field input[type=file]');
button.addEventListener("click", function onClick(e) {
e.preventDefault(); e.preventDefault();
e.target.removeEventListener("click", onClick); button.removeEventListener("click", onClick);
document.querySelector('.input-field input[type=file]').click(); document.querySelector('.input-field input[type=file]').click();
}); });
document.querySelector('.input-field input[type=file]')
.addEventListener("change", function onChange(e) { fileInput.addEventListener("change", function onChange(e) {
e.preventDefault(); e.preventDefault();
e.target.removeEventListener("change", onChange); fileInput.removeEventListener("change", onChange);
if (e.target.files && e.target.files.length) { if (e.target.files && e.target.files.length) {
self.decode(URL.createObjectURL(e.target.files[0])); self.decode(URL.createObjectURL(e.target.files[0]));
} }

@ -0,0 +1,80 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<title>index</title>
<meta name="description" content="" />
<meta name="author" content="Christoph Oberhofer" />
<meta name="viewport" content="width=device-width; initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="../css/fonts.css" />
<link rel="stylesheet" type="text/css" href="../css/styles.css" />
<link rel="stylesheet" type="text/css" href="./styles.css" />
<link rel="stylesheet" type="text/css" href="../css/prism.css" />
</head>
<body>
<header>
<div class="headline">
<h1>QuaggaJS</h1>
<h2>An advanced barcode-scanner written in JavaScript</h2>
</div>
</header>
<section id="container" class="container">
<div class="controls">
<h3>Scan various barcodes continously</h3>
<button type="button" class="icon-barcode button scan">Start Scanning</button>
<div class="readers">
<label>
<span>EAN-13</span>
<input type="checkbox" checked name="ean_reader" />
</label>
<label>
<span>EAN-8</span>
<input type="checkbox" name="ean_8_reader" />
</label>
<label>
<span>UPC-E</span>
<input type="checkbox" name="upc_e_reader" />
</label>
<label>
<span>Code 39</span>
<input type="checkbox" checked name="code_39_reader" />
</label>
<label>
<span>Codabar</span>
<input type="checkbox" name="codabar_reader" />
</label>
<label>
<span>Code 128</span>
<input type="checkbox" checked name="code_128_reader" />
</label>
<label>
<span>Interleaved 2 of 5</span>
<input type="checkbox" name="i2of5_reader" />
</label>
</div>
<p>
Be aware that not all combinations play together nicely. Some
codes do not have a checksum (e.g. ITF).
</p>
</div>
<div class="overlay overlay--inline">
<div class="overlay__content">
<div class="overlay__close">X</div>
</div>
</div>
</section>
<ul class="results"></ul>
<script src="../../dist/quagga.js" type="text/javascript"></script>
<script src="index.js" type="text/javascript"></script>
<script src="../vendor/prism.js"></script>
</body>
</html>

@ -0,0 +1,96 @@
var Quagga = window.Quagga;
var App = {
_lastResult: null,
init: function() {
this.attachListeners();
},
activateScanner: function() {
var scanner = this.configureScanner('.overlay__content'),
onDetected = function (result) {
this.addToResults(result);
}.bind(this),
stop = function() {
scanner.stop(); // should also clear all event-listeners?
scanner.removeEventListener('detected', onDetected);
this.hideOverlay();
this.attachListeners();
}.bind(this);
this.showOverlay(stop);
console.log("activateScanner");
scanner.addEventListener('detected', onDetected).start();
},
addToResults: function(result) {
if (this._lastResult === result.codeResult.code) {
return;
}
this._lastResult = result.codeResult.code;
var results = document.querySelector('ul.results'),
li = document.createElement('li'),
format = document.createElement('span'),
code = document.createElement('span');
li.className = "result";
format.className = "format";
code.className = "code";
li.appendChild(format);
li.appendChild(code);
format.appendChild(document.createTextNode(result.codeResult.format));
code.appendChild(document.createTextNode(result.codeResult.code));
results.insertBefore(li, results.firstChild);
},
attachListeners: function() {
var button = document.querySelector('button.scan'),
self = this;
button.addEventListener("click", function clickListener (e) {
e.preventDefault();
button.removeEventListener("click", clickListener);
self.activateScanner();
});
},
showOverlay: function(cancelCb) {
document.querySelector('.container .controls')
.classList.add('hide');
document.querySelector('.overlay--inline')
.classList.add('show');
var closeButton = document.querySelector('.overlay__close');
closeButton.addEventListener('click', function closeHandler() {
closeButton.removeEventListener("click", closeHandler);
cancelCb();
});
},
hideOverlay: function() {
document.querySelector('.container .controls')
.classList.remove('hide');
document.querySelector('.overlay--inline')
.classList.remove('show');
},
querySelectedReaders: function() {
return Array.prototype.slice.call(document.querySelectorAll('.readers input[type=checkbox]'))
.filter(function(element) {
return !!element.checked;
})
.map(function(element) {
return element.getAttribute("name");
});
},
configureScanner: function(selector) {
var scanner = Quagga
.decoder({readers: this.querySelectedReaders()})
.locator({patchSize: 'medium'})
.fromVideo({
target: selector,
constraints: {
width: 600,
height: 600,
facingMode: "environment"
}
});
return scanner;
}
};
App.init();

@ -0,0 +1,140 @@
body {
display: flex;
flex-direction: column;
padding-bottom: 0;
height: 100%;
box-sizing: border-box;
}
body > header {
flex: 0 0 auto;
padding: 0.5rem 1rem;
}
* {
box-sizing: inherit;
}
header > .headline {
display: flex;
flex-direction: row;
align-items: center;
}
.headline h1, .headline h2 {
margin: 0;
}
.headline h2 {
font-size: 1.3rem;
text-align: right;
}
body > .container {
margin: 0;
flex: 1 1 auto;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
position: relative;
}
/* Controls */
/* Scan! Button */
.icon-barcode.scan {
font-size: x-large;
padding: 0.5rem;
text-align: center;
margin: 0 auto;
display: block;
width: 70%;
}
.icon-barcode.scan:before {
margin-right: 0.5rem;
}
/* Reader Checkboxes */
.controls .readers {
font-size: 1.3rem;
width: 70%;
margin: 2rem auto 0;
}
.controls .readers label {
display: flex;
flex-direction: row;
align-items: center;
}
.controls .readers input {
flex: 0 0 auto;
height: 1.5rem;
width: 1.5rem;
}
.controls .readers span {
flex: 1 1 auto;
}
/* Results */
body > .results {
flex: 0 0 auto;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
background-color: #DDD;
margin: 0;
padding: 0;
list-style-type: none;
padding: 0.25rem;
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
border-top: 1px solid #777;
}
.results > li {
flex: 0 1 auto;
margin: 0.25rem;
background: #fff;
border-radius: 2px;
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
}
.results:empty {
display: none;
}
.result {
display: flex;
flex-direction: column;
padding: 0.5rem;
}
.result > .format {
font-weight: bold;
}
.result > .code {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Scanner */
.container .controls.hide {
display: none;
}
.overlay--inline {
position: absolute;
display: none;
}
.overlay--inline.show {
display: block;
}

@ -47,7 +47,8 @@
<div class="collapsable-source"> <div class="collapsable-source">
<pre> <pre>
<code class="language-javascript"> <code class="language-javascript">
var App = { var Quagga = window.Quagga;
var App = {
_scanner: null, _scanner: null,
init: function() { init: function() {
this.attachListeners(); this.attachListeners();
@ -69,12 +70,12 @@
scanner.addEventListener('detected', onDetected).start(); scanner.addEventListener('detected', onDetected).start();
}, },
attachListeners: function() { attachListeners: function() {
var self = this; var self = this,
button = document.querySelector('.input-field input + button.scan');
document.querySelector('.input-field input + button.scan') button.addEventListener("click", function onClick(e) {
.addEventListener("click", function onClick(e) {
e.preventDefault(); e.preventDefault();
e.target.removeEventListener("click", onClick); button.removeEventListener("click", onClick);
self.activateScanner(); self.activateScanner();
}); });
}, },
@ -90,14 +91,17 @@
this._overlay.className = 'overlay'; this._overlay.className = 'overlay';
this._overlay.appendChild(content); this._overlay.appendChild(content);
content.appendChild(closeButton); content.appendChild(closeButton);
closeButton.addEventListener('click', function closeClick(e) { closeButton.addEventListener('click', function closeClick() {
e.target.removeEventListener('click', closeClick); closeButton.removeEventListener('click', closeClick);
cancelCb(); cancelCb();
}); });
document.body.appendChild(this._overlay); document.body.appendChild(this._overlay);
} else { } else {
var closeButton = document.querySelector('.overlay__close'); var closeButton = document.querySelector('.overlay__close');
closeButton.addEventListener('click', cancelCb); closeButton.addEventListener('click', function closeClick() {
closeButton.removeEventListener('click', closeClick);
cancelCb();
});
} }
this._overlay.style.display = "block"; this._overlay.style.display = "block";
}, },
@ -122,8 +126,8 @@
} }
return this._scanner; return this._scanner;
} }
}; };
App.init(); App.init();
</code> </code>
</pre> </pre>
</div> </div>

@ -21,12 +21,12 @@ var App = {
scanner.addEventListener('detected', onDetected).start(); scanner.addEventListener('detected', onDetected).start();
}, },
attachListeners: function() { attachListeners: function() {
var self = this; var self = this,
button = document.querySelector('.input-field input + button.scan');
document.querySelector('.input-field input + button.scan') button.addEventListener("click", function onClick(e) {
.addEventListener("click", function onClick(e) {
e.preventDefault(); e.preventDefault();
e.target.removeEventListener("click", onClick); button.removeEventListener("click", onClick);
self.activateScanner(); self.activateScanner();
}); });
}, },
@ -42,14 +42,17 @@ var App = {
this._overlay.className = 'overlay'; this._overlay.className = 'overlay';
this._overlay.appendChild(content); this._overlay.appendChild(content);
content.appendChild(closeButton); content.appendChild(closeButton);
closeButton.addEventListener('click', function closeClick(e) { closeButton.addEventListener('click', function closeClick() {
e.target.removeEventListener('click', closeClick); closeButton.removeEventListener('click', closeClick);
cancelCb(); cancelCb();
}); });
document.body.appendChild(this._overlay); document.body.appendChild(this._overlay);
} else { } else {
var closeButton = document.querySelector('.overlay__close'); var closeButton = document.querySelector('.overlay__close');
closeButton.addEventListener('click', cancelCb); closeButton.addEventListener('click', function closeClick() {
closeButton.removeEventListener('click', closeClick);
cancelCb();
});
} }
this._overlay.style.display = "block"; this._overlay.style.display = "block";
}, },

@ -60,7 +60,7 @@
"phantomjs": "^1.9.18", "phantomjs": "^1.9.18",
"sinon": "^1.16.1", "sinon": "^1.16.1",
"sinon-chai": "^2.8.0", "sinon-chai": "^2.8.0",
"webpack": "^2.1.0-beta.4", "webpack": "^2.1.0-beta.7",
"webpack-sources": "^0.1.1" "webpack-sources": "^0.1.1"
}, },
"directories": { "directories": {
@ -109,6 +109,6 @@
"lodash": "^4.6.1", "lodash": "^4.6.1",
"ndarray": "^1.0.18", "ndarray": "^1.0.18",
"ndarray-linear-interpolate": "^1.0.0", "ndarray-linear-interpolate": "^1.0.0",
"webrtc-adapter": "^1.0.6" "webrtc-adapter": "^1.2.2"
} }
} }

@ -50,10 +50,17 @@ export default function createEventedElement() {
var event = getEvent(eventName), var event = getEvent(eventName),
subscribers = event.subscribers; subscribers = event.subscribers;
event.subscribers = subscribers.filter(function(subscriber) { subscribers.filter(function(subscriber) {
return !!subscriber.once;
}).forEach((subscriber) => {
publishSubscription(subscriber, data); publishSubscription(subscriber, data);
});
event.subscribers = subscribers.filter(function(subscriber) {
return !subscriber.once; return !subscriber.once;
}); });
event.subscribers.forEach((subscriber) => {
publishSubscription(subscriber, data);
});
}, },
once: function(event, callback, async) { once: function(event, callback, async) {
subscribe(event, { subscribe(event, {

@ -36,11 +36,12 @@ function initCamera(video, constraints) {
.then((stream) => { .then((stream) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
streamRef = stream; streamRef = stream;
video.src = window.URL.createObjectURL(stream); video.setAttribute("autoplay", 'true');
video.onloadedmetadata = (e) => { video.srcObject = stream;
video.addEventListener('loadedmetadata', (e) => {
video.play(); video.play();
resolve(); resolve();
}; });
}); });
}) })
.then(waitForVideo.bind(null, video)); .then(waitForVideo.bind(null, video));

@ -48,7 +48,7 @@ function fromImage(config, imageSrc, inputConfig = {}) {
toPromise() { toPromise() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
scanner.decodeSingle(config, (result) => { scanner.decodeSingle(config, (result) => {
if (result.codeResult && result.codeResult.code) { if (result && result.codeResult && result.codeResult.code) {
return resolve(result); return resolve(result);
} }
return reject(result); return reject(result);
@ -80,7 +80,6 @@ function fromVideo(config, source, inputConfig = {}) {
} else if (typeof source === 'object' } else if (typeof source === 'object'
&& (typeof source.constraints !== 'undefined' && (typeof source.constraints !== 'undefined'
|| typeof source.area !== 'undefined')) { || typeof source.area !== 'undefined')) {
console.log("inputConfig");
inputConfig = source; inputConfig = source;
} else if (!source) { } else if (!source) {
// LiveStream // LiveStream

@ -69,7 +69,6 @@ function createScanner() {
} }
_inputStream.setAttribute("preload", "auto"); _inputStream.setAttribute("preload", "auto");
_inputStream.setAttribute("autoplay", true);
_inputStream.setInputStream(_config.inputStream); _inputStream.setInputStream(_config.inputStream);
_inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb)); _inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb));
} }

Loading…
Cancel
Save