implementing quagga scanning barcodes - web

I am making an online scan application just with HTML5 and javascript using Quagga.js.
I need to get the webcam working for searching barcodes and imported quagga.js :
On the web page of quagga you'll find a method called Quagga.init. to initialize the webcam view.
I entered in the script tags this code :
Quagga.init({
inputStream : {
name : "Live",
type : "LiveStream"
},
decoder : {
readers : ["code_128_reader"]
}
}, function() {
console.log("Initialization finished. Ready to start");
Quagga.start();
});
But nothing happened.
What do I need to do to get this webcam working?
Any other opinions to create a web-based application for scanning barcodes ?
Thank you for answering !

Include <div id="interactive" class="viewport"></div> into your markup.

It's a few months old question but Eugene's answer is not full. For me, to make QuaggaJS work I had to add video tag as well:
<div id="interactive" class="viewport">
<video autoplay="true" preload="auto"></video>
</div>

Have you checked your console?
Using "Livestream" (Access to Camera) requires you to have a SSL certified website.
It means the additional "s" in https://
You can read more about it here: https://support.google.com/adwords/answer/2580401?hl=sv
You should also know that you can get a free SSL certificat, but you need to have access to your server. Most hosting services can help you with this.

Add in html
<div id="barcode-scanner" class="size"> </div>
Add in JavaScript
Quagga.init({
inputStream : {
name : "Live",
type : "LiveStream",
target: document.querySelector('#barcode-scanner'),
constraints: {
width: 520,
height: 400,
facingMode: "user" //"environment" for back camera, "user" front camera
}
},
decoder : {
readers : ["code_128_reader","code_39_reader"]
}
}, function(err) {
if (err) {
esto.error = err;
console.log(err);
return
}
Quagga.start();
Quagga.onDetected(function(result) {
var last_code = result.codeResult.code;
console.log("last_code ");
});
});
Works for me in Vue.

Add a div element like this in your markup:
<div id="barcode_canvas"></div>
Then include the target in your input stream like this:
target: document.querySelector('#barcode_canvas')
Quagga.init({
inputStream : {
name : 'Live',
type : 'LiveStream',
target: document.querySelector('#barcode_canvas')
},
decoder : {
readers : ['ean_reader']
}
}, function(err) {
if (err) {
console.log(err);
return
}
console.log('Initialization finished. Ready to start');
Quagga.start();
});

Related

angular2 rxjs filter threads with input text

Hi I'm building a small stackoverflow-like forum and I'm trying to implement a simple text-filter for my threads-titles.
I've recently started learning about rxjs and pipes so this is what I came up so far with 2 issues
I'm not sure which method I should use to to parse the title, i'm currently using string.include() but it's not working correctly (e.g. if I type who, then "how" shows, if I type "how" then "who" shows...
UPDATE: Sofar the major error seems to be that the pipe only receives the first letter...but no clue on what causes it.
I'm using a pure pipe and the property gets passed to it via an subject,not sure if this is the best practice way...
https://plnkr.co/edit/VViLYFd5oFTwNqP9eoZi?p=preview
Thanks for help and suggestions
Component
#Component({
selector: 'dashboard-main',
pipes:[FilterTitle],
template:`
<input type="text" id="title" [(ngModel)]="binding" (keyup)="trigger()">
<h3>{{binding}}</h3>
<hr>
<h3>{{testText}}</h3>
<hr>
<ul>
<li *ngFor="#thread of threadlist | filterTitle:testText">{{thread.title}}</li>
</ul>
`
})
export class DashboardMainComponent implements OnInit{
binding:string='Input';
text$:Subject<string> = new Subject<string>();
testText:string="";
ngOnInit():any {
this.text$.debounceTime(500).distinctUntilChanged().subscribe( text => this.setText(text))
}
trigger(){
this.text$.next(this.binding);
}
setText(text:string){
console.log(text);
this.testText = text;
}
threadlist=[
{
title:'Who are you?'
},
{
title:'How are you?'
},
{
title:'Where are you?'
}
]
}
Pipe
#Pipe({
name:'filterTitle',
})
export class FilterTitle implements PipeTransform{
transform(array:any[], [search]):any {
if(search ===''){
return array
}
return array.filter(thread => {
return thread.title.includes(search)
})
}
}
The parameter declaration in the pipe was wrong. It should be
transform(array:any[], search):any {
instead of
transform(array:any[], [search]):any {
Since beta.16 pipes don't get an array or parameters passed anymore. Each value is passed as a distinctive parameter https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26
Plunker example

Changing src attribute for an audio element doesn't work

Changing src attribute for an audio element doesn't work:
var Audio = React.createClass({
render : function() {
return (
<audio src={this.props.data.songUrl}/>
);
}
});
var Music = React.createClass({
render : function() {
return (
<article className="music">
<article className="musicContent">
<MusicButton data={Data} />
<List />
<Footer />
</article>
</article>
);
}
});
var MusicButton = React.createClass({
getInitialState : function() {
return {
isPlay : true,
count : 0
}
},
musicPlay : function () {
var audio = React.findDOMNode(this.refs.audio);
if(this.state.isPlay) {
audio.play();
this.setState({isPlay: false});
} else {
audio.pause();
this.setState({isPlay: true});
}
},
getBackWardMusic : function() {
this.setState({count: ++this.state.count});
var audio = React.findDOMNode(this.refs.audio);
audio.play();
},
getForwardMusic : function() {
this.setState({count: --this.state.count});
var audio = React.findDOMNode(this.refs.audio);
audio.play();
},
render : function() {
var classString = 'iconMusic icon-pause';
if(this.state.isPlay) {
classString = 'iconMusic icon-pause';
} else {
classString += ' rotate';
}
return (
<header className="musicHeader">
<Audio ref="audio" data={this.props.data[this.state.count]} />
<span onClick={this.getBackWardMusic} className="iconMusic icon-backward"></span>
<span onClick={this.musicPlay} className={classString}></span>
<span onClick={this.getForwardMusic} className="iconMusic icon-forward"></span>
</header>
);
}
});
after changing the source of audio you need to .load() first, before play() plays the new source.
you may like to use .oncanplaythroug = .play()
I don't have a specific answer for your question but I've found that media elements have their own lifecycle that I'm not sure is handled correctly in the React wrappers. The React and media element lifecycles have subtle interactions that are difficult to get right.
E.g., in Chrome, media elements don't release their resources unless you set src='' and if you do this in a React class, followed by a src='something-else' then I suspect the src='' can get optimised away.
To manage a video element, for example, I wrapped it in a React component and attached my own event listeners to the video DOM element to help manage its state and also managed cases like src='' and others by directly manipulating the DOM element in componentWillReceiveProps and componentWillUpdate based on what was changing.
Sorry I've not given a complete answer. It would take a lot of time to completely describe everything but I hope this helps a bit.

Instafeed and Masonry

I have this code below where I am trying to use Instafeed and Masonry together. Everything works fine until I click the "Load more" button. Then the Masonry layout breaks. It's probably because something is loading before the other or vice versa. I'm new to this so all help would be greatly appreciated.
I got the tip to use imagesLoaded instead of window.load and also to use appended method. But I don't understand how to incorporate that in to my code.
My code is in a script.js doc and outputs in the footer of the page after instafeed.js and masonry.
$(function () {
var loadButton = document.getElementById('load-more');
if(loadButton !== null) {
var userFeed = new Instafeed({
get: 'user',
userId: xxxxxxxxx,
accessToken: 'xxxxxxxxx',
limit: 6,
resolution: 'standard_resolution',
template: '<div class="col30 grid image-top-fill instapic"><img src="{{image}}" alt="Instagram" /> <p class="nomargin">{{caption}}</p></div>',
after: function() {
if (!this.hasNext()) {
loadButton.setAttribute('disabled', 'disabled');
Masonry.start();
}
}
});
loadButton.addEventListener('click', function() {
userFeed.next();
});
userFeed.run();
}
});
$(window).load(function(){
var container = document.querySelector('#instafeed');
var msnry = new Masonry( container, {
itemSelector : '.instapic',
isAnimated : true,
isFitWidth : false
});
});
Thanks in advance for your help! Let me know if there is anything more you need from me.
Cheers / Jeppe
You're correct in that Masonry is trying to work with elements before they're loaded. You can put .masonry('appended', $items) in the after event of Instafeed. Instafeed's developer posted this fix:
https://github.com/stevenschobert/instafeed.js/issues/118#issuecomment-44438003

How to load YouTube API locally?

I need to load the YouTube API locally (Google Extension not allowing external scripts). So I downloaded the files into my directory:
https://www.youtube.com/player_api
https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl4qCmf3.js
However, when I try to programmatically inject this via a content script, it gives the following error:
Uncaught ReferenceError: YTConfig is not defined
To the OP: You were almost there! I'd like to acknowledge Jonathan Waldman, MSDN author, for mentioning this technique during one of his training sessions...
To review, YTConfig is defined at:
http://www.youtube.com/iframe_api
And here:
http://www.youtube.com/player_api
The iframe_api is the preferred link to use.
To recap, the links you provide above each link to JS code:
https://www.youtube.com/player_api
https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl4qCmf3.js
You also need a Div tag with an id of "player" and another Script tag that lets you specify which video you want to see. So there are four Script tags total:
For content in iframe_api
For content at https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl4qCmf3.js
For the player Div tag:
<div id="player"></div>
For JavaScript that configures the video
This translates loosely to:
<script>...place the player Div here</script>
<script>...place code from www-widgetapi-vfl4qCmf3.js here...</script>
<script>...place code from iframe_api here...</script>
<script>...place the code below here</script>
Here is the code for the final Script tag (note that you will likely want to change the videoId property so that it points to the ID of the desired video on the YouTube site):
<script>
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
When I did the above, the page worked and I had all of the YouTube code local to my development machine.

Knockout mapping plugin does not handle hierarchical data properly

I have hierarchical JSON structure that differs after every new JSON from the server side. Given my template, this does not adequately show model update.
After troubleshooting, I noticed the mapping plugin does not correctly map child elements(or perhaps I am doing it incorrectly)
I can also track the memory keeps growing for every update in the datamodel.
Any help will be greatly appreciated.
This simple test is up on JSFiddle http://jsfiddle.net/Bru5a/1/
Here is my view
<div id="view">
The behavior is different depending on the order you load the model.
First
Second
Third
<span data-bind="text: name"></span>
<div data-bind="if: $data.child">
<b data-bind="text: child.name"></b>
<div data-bind="if: child.sub">
<b data-bind="text: child.sub.name"></b>
</div>
</div>
</div>
Here is my Javascript:
var BaseModel = function(om) {
ko.mapping.fromJS(om, {}, this);
};
var resourceModel = null;
function applyJson(json) {
try {
if(resourceModel){
ko.mapping.fromJS(json, {} ,resourceModel);
} else {
resourceModel = new BaseModel(json);
ko.applyBindings(resourceModel, $("#view")[0]);
}
} catch(e) {
alert(e);
}
}
function loadFirst() {
var json = { "name" : "1",
"child" : {
"name": "Child One"
}
};
applyJson(json);
}
function loadSecond() {
var json = { "name" : "2" };
applyJson(json);
}
function loadThird() {
var json = { "name" : "3",
"child" : {
"name": "Child Three",
"sub" : {
"name" : "Third Sub Child"
}
}
};
applyJson(json);
}
$(document).ready(function () {
$("#second").click(function(){
loadSecond();
});
$("#third").click(function(){
loadThird();
});
$("#first").click(function(){
loadFirst();
});
});​
What is happening in your case, is that knockout is behaving as designed.
To see what is happening, add the following line inside your outer div
<div data-bind="text: ko.toJSON($root)"></div>
You can see what is being bound in your view model.
To understand what is being displayed, Watch what is happening the to the viewmodel as you select the different links. As you update your model, you will see that once a property has been created, it remains there. This is by design of how the mapper works.
Next, you have to remember that ko.applyBindings is only being called ONE time. Therefore, the binding are only being applied one time to the properties that are in existence at the time the applyBindings is called. When you add properties to your viewmodel later, they will not automatically be bound to the data-bindings.
To make this example work, you will need to re-think your view model so that all the properties are present at the time you call apply bindings.
EDIT
I've edited your fiddle to show what I was talking about at http://jsfiddle.net/photo_tom/Bru5a/5/

Resources