Skip to content

Commit

Permalink
Add HTTP POST for scan results. Add settings UI for managing HTTP POS…
Browse files Browse the repository at this point in the history
…Ts. Rename linkAction 'ignore' to 'none'.
  • Loading branch information
schmich committed Jun 29, 2016
1 parent dc6ca78 commit 18eee51
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 17 deletions.
92 changes: 82 additions & 10 deletions app.js
Expand Up @@ -20,9 +20,15 @@ var app = new Vue({
pattern: '',
output: ''
},
currentHttpAction: {
url: '',
captureImage: false,
enabling: false
},
scans: store.get('scans') || [],
transforms: store.get('transforms') || [],
linkAction: store.get('link-action') || 'ignore',
linkAction: store.get('link-action') || 'none',
httpAction: store.get('http-action') || { enabled: false },
activeCamera: store.get('active-camera') || null,
playAudio: store.get('play-audio') || false,
allowBackgroundScan: store.get('background-scan') || false
Expand Down Expand Up @@ -71,6 +77,20 @@ var app = new Vue({
self.store.set('background-scan', allowBackgroundScan);
});

this.$watch('httpAction', function (action) {
self.store.set('http-action', action);
}, { deep: true });

this.$watch('httpAction.captureImage', function (capture) {
scanner.setCaptureImage(capture);
});

this.$watch('httpAction.enabled', function (enabled) {
if (enabled) {
this.editHttpAction(true);
}
});

new Clipboard('.clipboard-copy', {
text: function (trigger) {
return trigger.dataset.clipboard;
Expand Down Expand Up @@ -139,11 +159,40 @@ var app = new Vue({
this.transforms.splice(index, 1);
},

editHttpAction: function (enabling = false) {
this.currentHttpAction.url = this.httpAction.url;
this.currentHttpAction.captureImage = this.httpAction.captureImage;
this.currentHttpAction.enabling = enabling;
$('#http-action-dialog').modal();
},

closeHttpActionDialog: function () {
$('#http-action-dialog').modal('hide');
},

cancelHttpActionDialog: function () {
if (this.currentHttpAction.enabling) {
this.httpAction.enabled = false;
}

this.closeHttpActionDialog();
},

acceptHttpActionDialog: function () {
this.httpAction.url = this.currentHttpAction.url;
this.httpAction.captureImage = this.currentHttpAction.captureImage;
this.closeHttpActionDialog();
},

addScan: function (content) {
this.scans.push({
var scan = {
content: content,
date: +(new Date())
});
};

this.scans.push(scan);

return scan;
},

deleteScan: function (scan) {
Expand All @@ -164,11 +213,15 @@ var app = new Vue({
return string.match(/^https?:\/\//i);
},

onScanResult: function (content) {
onScanResult: function (content, image) {
content = this.transform(content);

var isHttpUrl = this.isHttpUrl(content);

if (this.playAudio) {
this.chime.play();
}

var snackbarContent = 'Scanned: '
+ content
+ '<a href="#" class="clipboard-copy" data-dismiss="snackbar" data-clipboard="'
Expand All @@ -182,25 +235,44 @@ var app = new Vue({
+ '<span class="icon icon-md">call_made</span> Open</a>';
}

if (this.playAudio) {
this.chime.play();
}

$('body').snackbar({
alive: 5 * 1000,
content: snackbarContent
});

this.addScan(content);
var scan = this.addScan(content);

if (this.linkAction !== 'ignore' && isHttpUrl) {
if (this.linkAction !== 'none' && isHttpUrl) {
if (this.linkAction === 'new-tab') {
var win = window.open(content, '_blank');
win.focus();
} else if (this.linkAction === 'current-tab') {
window.location = content;
}
}

if (this.httpAction.enabled) {
var body = {
content: scan.content,
date: scan.date
};

if (image) {
body.image = image;
}

$.ajax({
method: 'POST',
url: this.httpAction.url,
contentType: 'application/json',
data: JSON.stringify(body),
processData: false
}).done(function () {
// TODO.
}).fail(function () {
// TODO.
});
}
}
}
});
Expand Down
45 changes: 43 additions & 2 deletions index.html
Expand Up @@ -94,6 +94,13 @@ <h4>After scanning</h4>
Play a sound
</label>
</div>
<div class="checkbox switch">
<label for="http-action">
<input class="access-hide" id="http-action" name="http-action" type="checkbox" v-model="httpAction.enabled"><span class="switch-toggle"></span>
POST to a URL
</label>
<span v-if="httpAction.enabled">&ndash; <a @click="editHttpAction()">Edit</a></span>
</div>
</div>
</fieldset>
</form>
Expand All @@ -102,8 +109,8 @@ <h4>After scanning a link</h4>
<fieldset>
<div class="form-group">
<div class="radiobtn radiobtn-adv">
<label for="link-ignore">
<input class="access-hide" id="link-ignore" name="link" type="radio" value="ignore" v-model="linkAction">
<label for="link-none">
<input class="access-hide" id="link-none" name="link" type="radio" value="none" v-model="linkAction">
Do nothing
<span class="radiobtn-circle"></span><span class="radiobtn-circle-check"></span>
</label>
Expand Down Expand Up @@ -219,6 +226,40 @@ <h4>Transforms</h4>
</div>
</div>
</div>
<div aria-hidden="true" class="modal modal-va-middle fade" id="http-action-dialog" role="dialog" tabindex="-1">
<div class="modal-dialog modal-xs">
<div class="modal-content">
<div class="modal-heading">
<p class="modal-title">POST Scanned Content to a URL</p>
</div>
<div class="modal-inner">
<form>
<fieldset>
<p>After scanning, the scanned content and image data will be POSTed to the URL specified below.</p>
<p>If the URL is on another domain, it needs to have <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS" target="_blank">CORS enabled</a> to POST from the current domain.</p>
<div class="form-group form-group-label">
<label class="floating-label" for="url">URL Endpoint</label>
<input class="form-control" id="url" type="text" v-model="currentHttpAction.url">
</div>
<div class="checkbox checkbox-adv">
<label for="post-image">
<input class="access-hide" id="post-image" name="post-image" type="checkbox" v-model="currentHttpAction.captureImage">
Include base64-encoded image data in payload
<span class="checkbox-circle"></span><span class="checkbox-circle-check"></span><span class="checkbox-circle-icon icon">done</span>
</label>
</div>
</fieldset>
</form>
</div>
<div class="modal-footer">
<p class="text-right">
<a class="btn btn-flat btn-brand-accent waves-attach" @click="cancelHttpActionDialog()">Cancel</a>
<a class="btn btn-flat btn-brand-accent waves-attach" @click="acceptHttpActionDialog()">OK</a>
</p>
</div>
</div>
</div>
</div>
<div class="overlay">
<a id="menu-button" class="fbtn fbtn-brand fbtn-lg waves-attach waves-circle" data-toggle="menu" href="#history-menu">
<span class="icon icon-lg">history</span>
Expand Down
18 changes: 13 additions & 5 deletions qr.js
Expand Up @@ -5,6 +5,7 @@ function CameraQrScanner(previewContainer) {
this.scanActive = false;
this.lastResult = null;
this.refractoryTimeout = null;
this.captureImage = false;

var cameraElement = document.createElement('video');
cameraElement.setAttribute('autoplay', 'autoplay');
Expand Down Expand Up @@ -50,6 +51,7 @@ function CameraQrScanner(previewContainer) {
cameraElement.src = window.URL.createObjectURL(stream);
startScan();
}, function (err) {
// TODO.
});
};

Expand All @@ -65,7 +67,11 @@ function CameraQrScanner(previewContainer) {
}
};

var image;
this.setCaptureImage = function (captureImage) {
this.captureImage = captureImage;
};

this.imageBuffer = null;
var context;

var sensorLeft;
Expand Down Expand Up @@ -107,7 +113,7 @@ function CameraQrScanner(previewContainer) {
return;
}

if (!image) {
if (!this.imageBuffer) {
var videoWidth = cameraElement.videoWidth;
var videoHeight = cameraElement.videoHeight;

Expand All @@ -119,15 +125,15 @@ function CameraQrScanner(previewContainer) {
canvas.height = sensorHeight;

context = canvas.getContext('2d');
image = ZXing._resize(sensorWidth, sensorHeight);
this.imageBuffer = ZXing._resize(sensorWidth, sensorHeight);
return;
}

context.drawImage(cameraElement, sensorLeft, sensorTop, sensorWidth, sensorHeight, 0, 0, sensorWidth, sensorHeight);
var data = context.getImageData(0, 0, sensorWidth, sensorHeight).data;

for (var i = 0, j = 0; i < data.length; i += 4, j++) {
ZXing.HEAPU8[image + j] = data[i];
ZXing.HEAPU8[this.imageBuffer + j] = data[i];
}

var err = ZXing._decode_qr(decodeCallback);
Expand All @@ -142,9 +148,11 @@ function CameraQrScanner(previewContainer) {
self.lastResult = null;
}, 5 * 1000);

var image = self.captureImage ? canvas.toDataURL('image/webp', 0.8) : null;

self.lastResult = result;
setTimeout(function () {
self.onResult(result);
self.onResult(result, image);
}, 0);
}
}
Expand Down
3 changes: 3 additions & 0 deletions style.css
Expand Up @@ -4,6 +4,9 @@ html, body {
background: #000;
overflow: hidden;
}
a {
cursor: pointer !important;
}
video {
margin: 0;
padding: 0;
Expand Down

0 comments on commit 18eee51

Please sign in to comment.