jpeg_camera 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +21 -0
- data/README.md +146 -0
- data/lib/jpeg_camera.rb +6 -0
- data/lib/jpeg_camera/version.rb +8 -0
- data/vendor/assets/audios/jpeg_camera/shutter.mp3 +0 -0
- data/vendor/assets/images/jpeg_camera/jpeg_camera.swf +0 -0
- data/vendor/assets/javascripts/jpeg_camera/canvas-to-blob.js +95 -0
- data/vendor/assets/javascripts/jpeg_camera/canvas-to-blob.min.js +1 -0
- data/vendor/assets/javascripts/jpeg_camera/jpeg_camera.js +736 -0
- data/vendor/assets/javascripts/jpeg_camera/jpeg_camera.min.js +4 -0
- data/vendor/assets/javascripts/jpeg_camera/jpeg_camera_no_flash.js +616 -0
- data/vendor/assets/javascripts/jpeg_camera/jpeg_camera_no_flash.min.js +4 -0
- data/vendor/assets/javascripts/jpeg_camera/swfobject.js +777 -0
- data/vendor/assets/javascripts/jpeg_camera/swfobject.min.js +4 -0
- metadata +72 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 64570f77a25c5034e335b4e59440007d56ceb361
|
4
|
+
data.tar.gz: 793cce21b60946b0f6b9e7d56d180ef900de62f1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6b0d9f6c6d15429d8c0dae0faf16d9850912f658cd26ffe6dfd54a4f927afc8821aaf0f33e6f628fee0851c7f93ef0f3e7da4ec33413efc7f371d5637bda69ff
|
7
|
+
data.tar.gz: 955210d1bd55c3697eb8801e2e2b131ba068e8acb7b732e380117c312ddc31006a8013ac0bad7cba1a3feaabd912d3d0be0e2a6c6bbe5d0bbbc7588f63db73a5
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Adam Wróbel
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
## About
|
2
|
+
|
3
|
+
JpegCamera is a JavaScript library that allows you display a camera stream on
|
4
|
+
a web page and then capture, show and upload JPEG snapshots to the server. It
|
5
|
+
uses HTML5 in Chrome, Firefox and Opera and falls back to Flash in less capable
|
6
|
+
browsers. The video stream is placed without any UI in a container of your
|
7
|
+
choice and you control it through JavaScript API and your own UI elements.
|
8
|
+
|
9
|
+
The idea is based on a similar
|
10
|
+
[JpegCam](https://github.com/mattclements/jpegcam) library which was Flash only.
|
11
|
+
Beside working without Flash and offering a cleaner, more modern API, JpegCamera
|
12
|
+
has some nice, new features.
|
13
|
+
|
14
|
+
## Features
|
15
|
+
|
16
|
+
- Works natively in Chrome, Firefox, Opera and with a Flash plugin in all other
|
17
|
+
browsers.
|
18
|
+
- Manage and upload multiple snapshots at once. You don't have to wait for the
|
19
|
+
first upload to finish before capturing the next image. This means you can
|
20
|
+
take a few shots in a short interval.
|
21
|
+
- Allows you to retry failed uploads.
|
22
|
+
- Easily read server response text and code after upload.
|
23
|
+
- Send CSRF tokens to secure your user's session from [Cross-site request
|
24
|
+
forgery](http://en.wikipedia.org/wiki/Cross-site_request_forgery#Prevention)
|
25
|
+
|
26
|
+
## Dependencies
|
27
|
+
|
28
|
+
- [Canvas-to-Blob](https://github.com/blueimp/JavaScript-Canvas-to-Blob)
|
29
|
+
polyfill for the standard JavaScript `canvas.toBlob` method.
|
30
|
+
- [SWFObject](http://code.google.com/p/swfobject/) for embedding the
|
31
|
+
Flash-based fallback.
|
32
|
+
|
33
|
+
For convenience these scripts are packaged with JpegCamera.
|
34
|
+
|
35
|
+
## Installation
|
36
|
+
|
37
|
+
You can load JpegCamera directly on any web page, but if you're writing Rails
|
38
|
+
3.1 application consider using a gem. In either case you have an option
|
39
|
+
of loading full library that includes HTML5 implementation with Flash fallback
|
40
|
+
or HTML5 version only.
|
41
|
+
|
42
|
+
### Standalone app
|
43
|
+
|
44
|
+
Copy all the files from `dist` into `jpeg_camera` directory under your server's
|
45
|
+
root.
|
46
|
+
|
47
|
+
Load JpegCamera and it's dependencies in the `HEAD` section of your page.
|
48
|
+
|
49
|
+
<script src="/jpeg_camera/swfobject.min.js" type="text/javascript"></script>
|
50
|
+
<script src="/jpeg_camera/canvas-to-blob.min.js" type="text/javascript"></script>
|
51
|
+
<script src="/jpeg_camera/jpeg_camera.min.js" type="text/javascript"></script>
|
52
|
+
|
53
|
+
SWFObject and Canvas-to-Blob are stored in separate files so that you don't have
|
54
|
+
to load them again if you already use them in your project. If you want to cut
|
55
|
+
down on HTTP requests then there is a concatenated version you can use.
|
56
|
+
|
57
|
+
<script src="/jpeg_camera/jpeg_camera_with_dependencies.min.js" type="text/javascript"></script>
|
58
|
+
|
59
|
+
If you want to use HTML5-only version you can load jpeg_camera_no_flash.min.js.
|
60
|
+
There is no "with dependencies" version of this file, so you have to remember
|
61
|
+
to also load Canvas-to-Blob. You don't need SWFObject for HTML5.
|
62
|
+
|
63
|
+
### Ruby on Rails 3.1 applications
|
64
|
+
|
65
|
+
Require the gem in your Gemfile.
|
66
|
+
|
67
|
+
gem "jpeg_camera", "~> 1.0.0"
|
68
|
+
|
69
|
+
Add appropriate requires to your application.js. SWFObject and Canvas-to-Blob
|
70
|
+
are stored in separate files so that you don't have to load them again if you
|
71
|
+
already use them in your project. The assets pipeline will take care of
|
72
|
+
minifying and concatenating everything into one script.
|
73
|
+
|
74
|
+
//= require jpeg_camera/swfobject
|
75
|
+
//= require jpeg_camera/canvas-to-blob
|
76
|
+
//= require jpeg_camera/jpeg_camera
|
77
|
+
|
78
|
+
If you want to use HTML5-only version then use this instead:
|
79
|
+
|
80
|
+
//= require jpeg_camera/canvas-to-blob
|
81
|
+
//= require jpeg_camera/jpeg_camera_no_flash
|
82
|
+
|
83
|
+
Minified versions of all the scripts are also included in the gem if you don't
|
84
|
+
want to include JpegCamera in your application.js file and would rather use
|
85
|
+
`javascript_include_tag` on select pages of your application.
|
86
|
+
|
87
|
+
## Usage
|
88
|
+
|
89
|
+
var camera = new JpegCamera("#camera");
|
90
|
+
|
91
|
+
var snapshot = camera.capture();
|
92
|
+
|
93
|
+
snapshot.show(); // Display the snapshot
|
94
|
+
|
95
|
+
snapshot.upload({api_url: "/upload_image"}).done(function(response) {
|
96
|
+
response_container.innerHTML = response;
|
97
|
+
this.discard(); // discard snapshot and show video stream again
|
98
|
+
}).fail(function() {
|
99
|
+
alert("Upload failed.");
|
100
|
+
});
|
101
|
+
|
102
|
+
A detailed documentation using in-code comments is maintained for
|
103
|
+
[JpegCamera](http://amw.github.io/jpeg_camera/doc/classes/JpegCamera.html) and
|
104
|
+
[Snapshot](http://amw.github.io/jpeg_camera/doc/classes/Snapshot.html)
|
105
|
+
classes.
|
106
|
+
|
107
|
+
## Caveats
|
108
|
+
|
109
|
+
To use Flash fallback your camera container must be at least 215 pixels wide and
|
110
|
+
138 pixels tall. This is the minimum to display privacy settings dialog.
|
111
|
+
|
112
|
+
With Flash in some browsers it's impossible to read response body for requests
|
113
|
+
that finish with status codes from outside the 2XX range (like 404 Not Found or
|
114
|
+
422 Unprocessable Entity). If you're using version of JpegCamera with Flash
|
115
|
+
fallback your application should not rely on reading body of these responses.
|
116
|
+
The status code number is always available.
|
117
|
+
|
118
|
+
## Contributing
|
119
|
+
|
120
|
+
The source code is available on [Github](https://github.com/amw/jpeg_camera).
|
121
|
+
Please send pull requests on topic branches.
|
122
|
+
|
123
|
+
To build dist files from source you need `npm` — Node Package Manager.
|
124
|
+
|
125
|
+
npm install # install required dependencies
|
126
|
+
npm install -g grunt-cli # install grunt command
|
127
|
+
grunt dist # build js & swf files
|
128
|
+
grunt js # only builds js files
|
129
|
+
grunt swf # only builds swf file
|
130
|
+
grunt doc # update documentation
|
131
|
+
grunt # build dist files and update documentation
|
132
|
+
|
133
|
+
To build swf file you need to have `mxmlc` available in your `$PATH`. It comes
|
134
|
+
in the [Flex SDK](http://www.adobe.com/devnet/flex/flex-sdk-download.html).
|
135
|
+
|
136
|
+
## Acknowledgements
|
137
|
+
|
138
|
+
Thanks to Joseph Huckaby for creating and Matt Clements for maintaining
|
139
|
+
Flash-based [JpegCam library](http://code.google.com/p/jpegcam/) which I have
|
140
|
+
been using until HTML5 became a viable solution. If you're interested here's
|
141
|
+
[Matt's repo](https://github.com/mattclements/jpegcam) and here's
|
142
|
+
[mine](https://github.com/amw/jpegcam). Thanks to everyone else contributing to
|
143
|
+
that project.
|
144
|
+
|
145
|
+
|
146
|
+
Copyright [Adam Wróbel](http://adamwrobel.com), released under the MIT License.
|
data/lib/jpeg_camera.rb
ADDED
Binary file
|
Binary file
|
@@ -0,0 +1,95 @@
|
|
1
|
+
/*
|
2
|
+
* JavaScript Canvas to Blob 2.0.5
|
3
|
+
* https://github.com/blueimp/JavaScript-Canvas-to-Blob
|
4
|
+
*
|
5
|
+
* Copyright 2012, Sebastian Tschan
|
6
|
+
* https://blueimp.net
|
7
|
+
*
|
8
|
+
* Licensed under the MIT license:
|
9
|
+
* http://www.opensource.org/licenses/MIT
|
10
|
+
*
|
11
|
+
* Based on stackoverflow user Stoive's code snippet:
|
12
|
+
* http://stackoverflow.com/q/4998908
|
13
|
+
*/
|
14
|
+
|
15
|
+
/*jslint nomen: true, regexp: true */
|
16
|
+
/*global window, atob, Blob, ArrayBuffer, Uint8Array, define */
|
17
|
+
|
18
|
+
(function (window) {
|
19
|
+
'use strict';
|
20
|
+
var CanvasPrototype = window.HTMLCanvasElement &&
|
21
|
+
window.HTMLCanvasElement.prototype,
|
22
|
+
hasBlobConstructor = window.Blob && (function () {
|
23
|
+
try {
|
24
|
+
return Boolean(new Blob());
|
25
|
+
} catch (e) {
|
26
|
+
return false;
|
27
|
+
}
|
28
|
+
}()),
|
29
|
+
hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&
|
30
|
+
(function () {
|
31
|
+
try {
|
32
|
+
return new Blob([new Uint8Array(100)]).size === 100;
|
33
|
+
} catch (e) {
|
34
|
+
return false;
|
35
|
+
}
|
36
|
+
}()),
|
37
|
+
BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||
|
38
|
+
window.MozBlobBuilder || window.MSBlobBuilder,
|
39
|
+
dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&
|
40
|
+
window.ArrayBuffer && window.Uint8Array && function (dataURI) {
|
41
|
+
var byteString,
|
42
|
+
arrayBuffer,
|
43
|
+
intArray,
|
44
|
+
i,
|
45
|
+
mimeString,
|
46
|
+
bb;
|
47
|
+
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
|
48
|
+
// Convert base64 to raw binary data held in a string:
|
49
|
+
byteString = atob(dataURI.split(',')[1]);
|
50
|
+
} else {
|
51
|
+
// Convert base64/URLEncoded data component to raw binary data:
|
52
|
+
byteString = decodeURIComponent(dataURI.split(',')[1]);
|
53
|
+
}
|
54
|
+
// Write the bytes of the string to an ArrayBuffer:
|
55
|
+
arrayBuffer = new ArrayBuffer(byteString.length);
|
56
|
+
intArray = new Uint8Array(arrayBuffer);
|
57
|
+
for (i = 0; i < byteString.length; i += 1) {
|
58
|
+
intArray[i] = byteString.charCodeAt(i);
|
59
|
+
}
|
60
|
+
// Separate out the mime component:
|
61
|
+
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
62
|
+
// Write the ArrayBuffer (or ArrayBufferView) to a blob:
|
63
|
+
if (hasBlobConstructor) {
|
64
|
+
return new Blob(
|
65
|
+
[hasArrayBufferViewSupport ? intArray : arrayBuffer],
|
66
|
+
{type: mimeString}
|
67
|
+
);
|
68
|
+
}
|
69
|
+
bb = new BlobBuilder();
|
70
|
+
bb.append(arrayBuffer);
|
71
|
+
return bb.getBlob(mimeString);
|
72
|
+
};
|
73
|
+
if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
|
74
|
+
if (CanvasPrototype.mozGetAsFile) {
|
75
|
+
CanvasPrototype.toBlob = function (callback, type, quality) {
|
76
|
+
if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {
|
77
|
+
callback(dataURLtoBlob(this.toDataURL(type, quality)));
|
78
|
+
} else {
|
79
|
+
callback(this.mozGetAsFile('blob', type));
|
80
|
+
}
|
81
|
+
};
|
82
|
+
} else if (CanvasPrototype.toDataURL && dataURLtoBlob) {
|
83
|
+
CanvasPrototype.toBlob = function (callback, type, quality) {
|
84
|
+
callback(dataURLtoBlob(this.toDataURL(type, quality)));
|
85
|
+
};
|
86
|
+
}
|
87
|
+
}
|
88
|
+
if (typeof define === 'function' && define.amd) {
|
89
|
+
define(function () {
|
90
|
+
return dataURLtoBlob;
|
91
|
+
});
|
92
|
+
} else {
|
93
|
+
window.dataURLtoBlob = dataURLtoBlob;
|
94
|
+
}
|
95
|
+
}(this));
|
@@ -0,0 +1 @@
|
|
1
|
+
!function(t){"use strict";var e=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,n=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),o=n&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),r=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,i=(n||r)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,i,a,l,u,B;for(e=t.split(",")[0].indexOf("base64")>=0?atob(t.split(",")[1]):decodeURIComponent(t.split(",")[1]),i=new ArrayBuffer(e.length),a=new Uint8Array(i),l=0;l<e.length;l+=1)a[l]=e.charCodeAt(l);return u=t.split(",")[0].split(":")[1].split(";")[0],n?new Blob([o?a:i],{type:u}):(B=new r,B.append(i),B.getBlob(u))};t.HTMLCanvasElement&&!e.toBlob&&(e.mozGetAsFile?e.toBlob=function(t,n,o){o&&e.toDataURL&&i?t(i(this.toDataURL(n,o))):t(this.mozGetAsFile("blob",n))}:e.toDataURL&&i&&(e.toBlob=function(t,e,n){t(i(this.toDataURL(e,n)))})),"function"==typeof define&&define.amd?define(function(){return i}):t.dataURLtoBlob=i}(this);
|
@@ -0,0 +1,736 @@
|
|
1
|
+
/*! JpegCamera 1.0.0 | 2013-07-29
|
2
|
+
(c) 2013 Adam Wrobel
|
3
|
+
http://amw.github.io/jpeg_camera */
|
4
|
+
(function() {
|
5
|
+
var JpegCamera, JpegCameraFlash, JpegCameraHtml5, Snapshot, supported_flash_version, _ref, _ref1,
|
6
|
+
__hasProp = {}.hasOwnProperty,
|
7
|
+
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
8
|
+
|
9
|
+
JpegCamera = (function() {
|
10
|
+
JpegCamera.DefaultOptions = {
|
11
|
+
shutter_url: "/jpeg_camera/shutter.mp3",
|
12
|
+
swf_url: "/jpeg_camera/jpeg_camera.swf",
|
13
|
+
on_debug: function(message) {
|
14
|
+
if (console && console.log) {
|
15
|
+
return console.log("JpegCamera: " + message);
|
16
|
+
}
|
17
|
+
},
|
18
|
+
quality: 0.9,
|
19
|
+
shutter: true,
|
20
|
+
mirror: false,
|
21
|
+
timeout: 0
|
22
|
+
};
|
23
|
+
|
24
|
+
function JpegCamera(container, options) {
|
25
|
+
if ("string" === typeof container) {
|
26
|
+
this.container = document.querySelector(container);
|
27
|
+
} else {
|
28
|
+
this.container = container;
|
29
|
+
}
|
30
|
+
if (!(this.container && this.container.offsetWidth)) {
|
31
|
+
throw "JpegCamera: invalid container";
|
32
|
+
}
|
33
|
+
this.container.innerHTML = "";
|
34
|
+
this.options = this._extend({}, this.constructor.DefaultOptions, options);
|
35
|
+
this._engine_init();
|
36
|
+
}
|
37
|
+
|
38
|
+
JpegCamera.prototype.ready = function(callback) {
|
39
|
+
this.options.on_ready = callback;
|
40
|
+
if (this.options.on_ready && this._is_ready) {
|
41
|
+
this.options.on_ready.call(this);
|
42
|
+
}
|
43
|
+
return this;
|
44
|
+
};
|
45
|
+
|
46
|
+
JpegCamera.prototype._is_ready = false;
|
47
|
+
|
48
|
+
JpegCamera.prototype.error = function(callback) {
|
49
|
+
this.options.on_error = callback;
|
50
|
+
if (this.options.on_error && this._error_occured) {
|
51
|
+
this.options.on_error.call(this, this._error_occured);
|
52
|
+
}
|
53
|
+
return this;
|
54
|
+
};
|
55
|
+
|
56
|
+
JpegCamera.prototype._error_occured = false;
|
57
|
+
|
58
|
+
JpegCamera.prototype.capture = function(options) {
|
59
|
+
var snapshot, _options;
|
60
|
+
if (options == null) {
|
61
|
+
options = {};
|
62
|
+
}
|
63
|
+
snapshot = new Snapshot(this, options);
|
64
|
+
this._snapshots[snapshot.id] = snapshot;
|
65
|
+
_options = snapshot._options();
|
66
|
+
if (_options.shutter) {
|
67
|
+
this._engine_play_shutter_sound();
|
68
|
+
}
|
69
|
+
this._engine_capture(snapshot, _options.mirror, _options.quality);
|
70
|
+
return snapshot;
|
71
|
+
};
|
72
|
+
|
73
|
+
JpegCamera.prototype._snapshots = {};
|
74
|
+
|
75
|
+
JpegCamera.prototype.show_stream = function() {
|
76
|
+
this._engine_show_stream();
|
77
|
+
this._displayed_snapshot = null;
|
78
|
+
return this;
|
79
|
+
};
|
80
|
+
|
81
|
+
JpegCamera.prototype.discard_all = function() {
|
82
|
+
var id, snapshot, _ref;
|
83
|
+
if (this._displayed_snapshot) {
|
84
|
+
this.show_stream();
|
85
|
+
}
|
86
|
+
_ref = this._snapshots;
|
87
|
+
for (id in _ref) {
|
88
|
+
snapshot = _ref[id];
|
89
|
+
this._engine_discard(snapshot);
|
90
|
+
snapshot._discarded = true;
|
91
|
+
}
|
92
|
+
this._snapshots = {};
|
93
|
+
return this;
|
94
|
+
};
|
95
|
+
|
96
|
+
JpegCamera.prototype._extend = function(object) {
|
97
|
+
var key, source, sources, value, _i, _len;
|
98
|
+
sources = Array.prototype.slice.call(arguments, 1);
|
99
|
+
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
100
|
+
source = sources[_i];
|
101
|
+
if (source) {
|
102
|
+
for (key in source) {
|
103
|
+
value = source[key];
|
104
|
+
object[key] = value;
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
return object;
|
109
|
+
};
|
110
|
+
|
111
|
+
JpegCamera.prototype._debug = function(message) {
|
112
|
+
if (this.options.on_debug) {
|
113
|
+
return this.options.on_debug.call(this, message);
|
114
|
+
}
|
115
|
+
};
|
116
|
+
|
117
|
+
JpegCamera.prototype._view_width = function() {
|
118
|
+
return parseInt(this.container.offsetWidth, 10);
|
119
|
+
};
|
120
|
+
|
121
|
+
JpegCamera.prototype._view_height = function() {
|
122
|
+
return parseInt(this.container.offsetHeight, 10);
|
123
|
+
};
|
124
|
+
|
125
|
+
JpegCamera.prototype._display = function(snapshot) {
|
126
|
+
this._engine_display(snapshot);
|
127
|
+
return this._displayed_snapshot = snapshot;
|
128
|
+
};
|
129
|
+
|
130
|
+
JpegCamera.prototype._displayed_snapshot = null;
|
131
|
+
|
132
|
+
JpegCamera.prototype._upload = function(snapshot, api_url, csrf_token, timeout) {
|
133
|
+
return this._engine_upload(snapshot, api_url, csrf_token, timeout);
|
134
|
+
};
|
135
|
+
|
136
|
+
JpegCamera.prototype._discard = function(snapshot) {
|
137
|
+
if (this._displayed_snapshot === snapshot) {
|
138
|
+
this.show_stream();
|
139
|
+
}
|
140
|
+
this._engine_discard(snapshot);
|
141
|
+
snapshot._discarded = true;
|
142
|
+
return delete this._snapshots[snapshot.id];
|
143
|
+
};
|
144
|
+
|
145
|
+
JpegCamera.prototype._prepared = function() {
|
146
|
+
this._is_ready = true;
|
147
|
+
if (this.options.on_ready) {
|
148
|
+
return this.options.on_ready.call(this);
|
149
|
+
}
|
150
|
+
};
|
151
|
+
|
152
|
+
JpegCamera.prototype._got_error = function(error) {
|
153
|
+
this._debug("Error - " + error);
|
154
|
+
this._error_occured = error;
|
155
|
+
if (this.options.on_error) {
|
156
|
+
return this.options.on_error.call(this, this._error_occured);
|
157
|
+
}
|
158
|
+
};
|
159
|
+
|
160
|
+
return JpegCamera;
|
161
|
+
|
162
|
+
})();
|
163
|
+
|
164
|
+
navigator.getUserMedia || (navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
|
165
|
+
|
166
|
+
if (navigator.getUserMedia) {
|
167
|
+
JpegCameraHtml5 = (function(_super) {
|
168
|
+
__extends(JpegCameraHtml5, _super);
|
169
|
+
|
170
|
+
function JpegCameraHtml5() {
|
171
|
+
_ref = JpegCameraHtml5.__super__.constructor.apply(this, arguments);
|
172
|
+
return _ref;
|
173
|
+
}
|
174
|
+
|
175
|
+
JpegCameraHtml5.prototype._engine_init = function() {
|
176
|
+
var get_user_media_options, horizontal_padding, that, vertical_padding;
|
177
|
+
this._debug("Using HTML5 engine");
|
178
|
+
this.internal_container = document.createElement("div");
|
179
|
+
this.internal_container.style.width = "100%";
|
180
|
+
this.internal_container.style.height = "100%";
|
181
|
+
this.internal_container.style.position = "relative";
|
182
|
+
this.container.appendChild(this.internal_container);
|
183
|
+
vertical_padding = Math.floor(this._view_height() * 0.2);
|
184
|
+
horizontal_padding = Math.floor(this._view_width() * 0.2);
|
185
|
+
this.message = document.createElement("div");
|
186
|
+
this.message["class"] = "message";
|
187
|
+
this.message.style.width = "100%";
|
188
|
+
this.message.style.height = "100%";
|
189
|
+
this._add_prefixed_style(this.message, "boxSizing", "border-box");
|
190
|
+
this.message.style.overflow = "hidden";
|
191
|
+
this.message.style.textAlign = "center";
|
192
|
+
this.message.style.paddingTop = "" + vertical_padding + "px";
|
193
|
+
this.message.style.paddingBottom = "" + vertical_padding + "px";
|
194
|
+
this.message.style.paddingLeft = "" + horizontal_padding + "px";
|
195
|
+
this.message.style.paddingRight = "" + horizontal_padding + "px";
|
196
|
+
this.message.style.position = "absolute";
|
197
|
+
this.message.style.zIndex = 3;
|
198
|
+
this.message.innerHTML = "Please allow camera access when prompted by the browser.";
|
199
|
+
this.internal_container.appendChild(this.message);
|
200
|
+
this.video_container = document.createElement("div");
|
201
|
+
this.video_container.style.width = "" + (this._view_width()) + "px";
|
202
|
+
this.video_container.style.height = "" + (this._view_height()) + "px";
|
203
|
+
this.video_container.style.overflow = "hidden";
|
204
|
+
this.video_container.style.position = "absolute";
|
205
|
+
this.video_container.style.zIndex = 1;
|
206
|
+
this.internal_container.appendChild(this.video_container);
|
207
|
+
this.video = document.createElement('video');
|
208
|
+
this.video.autoplay = true;
|
209
|
+
this._add_prefixed_style(this.video, "transform", "scalex(-1.0)");
|
210
|
+
window.AudioContext || (window.AudioContext = window.webkitAudioContext);
|
211
|
+
if (window.AudioContext) {
|
212
|
+
this._load_shutter_sound();
|
213
|
+
}
|
214
|
+
get_user_media_options = {
|
215
|
+
video: {
|
216
|
+
optional: [
|
217
|
+
{
|
218
|
+
minWidth: 1280
|
219
|
+
}, {
|
220
|
+
minWidth: 640
|
221
|
+
}, {
|
222
|
+
minWidth: 480
|
223
|
+
}, {
|
224
|
+
minWidth: 360
|
225
|
+
}
|
226
|
+
]
|
227
|
+
}
|
228
|
+
};
|
229
|
+
that = this;
|
230
|
+
return navigator.getUserMedia(get_user_media_options, function(stream) {
|
231
|
+
that._remove_message();
|
232
|
+
if (window.URL) {
|
233
|
+
that.video.src = URL.createObjectURL(stream);
|
234
|
+
} else {
|
235
|
+
that.video.src = stream;
|
236
|
+
}
|
237
|
+
return that._wait_for_video_ready();
|
238
|
+
}, function(error) {
|
239
|
+
var code, key, value;
|
240
|
+
code = error.code;
|
241
|
+
for (key in error) {
|
242
|
+
value = error[key];
|
243
|
+
if (key === "code") {
|
244
|
+
continue;
|
245
|
+
}
|
246
|
+
that._got_error(key);
|
247
|
+
return;
|
248
|
+
}
|
249
|
+
return that._got_error("UNKNOWN ERROR");
|
250
|
+
});
|
251
|
+
};
|
252
|
+
|
253
|
+
JpegCameraHtml5.prototype._engine_play_shutter_sound = function() {
|
254
|
+
var source;
|
255
|
+
if (!this.shutter_buffer) {
|
256
|
+
return;
|
257
|
+
}
|
258
|
+
source = this.audio_context.createBufferSource();
|
259
|
+
source.buffer = this.shutter_buffer;
|
260
|
+
source.connect(this.audio_context.destination);
|
261
|
+
return source.start(0);
|
262
|
+
};
|
263
|
+
|
264
|
+
JpegCameraHtml5.prototype._engine_capture = function(snapshot, mirror, quality) {
|
265
|
+
var canvas, context, crop;
|
266
|
+
crop = this._get_capture_crop();
|
267
|
+
canvas = document.createElement("canvas");
|
268
|
+
canvas.width = crop.width;
|
269
|
+
canvas.height = crop.height;
|
270
|
+
context = canvas.getContext("2d");
|
271
|
+
context.drawImage(this.video, crop.x_offset, crop.y_offset, crop.width, crop.height, 0, 0, crop.width, crop.height);
|
272
|
+
snapshot._canvas = canvas;
|
273
|
+
snapshot._mirror = mirror;
|
274
|
+
return snapshot._quality = quality;
|
275
|
+
};
|
276
|
+
|
277
|
+
JpegCameraHtml5.prototype._engine_display = function(snapshot) {
|
278
|
+
if (this.displayed_canvas) {
|
279
|
+
this.internal_container.removeChild(this.displayed_canvas);
|
280
|
+
}
|
281
|
+
this.displayed_canvas = snapshot._canvas;
|
282
|
+
this.displayed_canvas.style.width = "" + (this._view_width()) + "px";
|
283
|
+
this.displayed_canvas.style.height = "" + (this._view_height()) + "px";
|
284
|
+
this.displayed_canvas.style.top = 0;
|
285
|
+
this.displayed_canvas.style.left = 0;
|
286
|
+
this.displayed_canvas.style.position = "absolute";
|
287
|
+
this.displayed_canvas.style.zIndex = 2;
|
288
|
+
this._add_prefixed_style(this.displayed_canvas, "transform", "scalex(-1.0)");
|
289
|
+
return this.internal_container.appendChild(this.displayed_canvas);
|
290
|
+
};
|
291
|
+
|
292
|
+
JpegCameraHtml5.prototype._engine_discard = function(snapshot) {
|
293
|
+
if (snapshot._xhr) {
|
294
|
+
snapshot._xhr.abort();
|
295
|
+
}
|
296
|
+
delete snapshot._xhr;
|
297
|
+
delete snapshot._canvas;
|
298
|
+
return delete snapshot._jpeg_blob;
|
299
|
+
};
|
300
|
+
|
301
|
+
JpegCameraHtml5.prototype._engine_show_stream = function() {
|
302
|
+
if (this.displayed_canvas) {
|
303
|
+
this.internal_container.removeChild(this.displayed_canvas);
|
304
|
+
this.displayed_canvas = null;
|
305
|
+
}
|
306
|
+
return this.video_container.style.display = "block";
|
307
|
+
};
|
308
|
+
|
309
|
+
JpegCameraHtml5.prototype._engine_upload = function(snapshot, api_url, csrf_token, timeout) {
|
310
|
+
var canvas, context, handler, that, xhr;
|
311
|
+
that = this;
|
312
|
+
if (snapshot._jpeg_blob) {
|
313
|
+
this._debug("Uploading the file");
|
314
|
+
handler = function(event) {
|
315
|
+
delete snapshot._xhr;
|
316
|
+
snapshot._status = event.target.status;
|
317
|
+
snapshot._response = event.target.responseText;
|
318
|
+
if (snapshot._status >= 200 && snapshot._status < 300) {
|
319
|
+
return snapshot._upload_done();
|
320
|
+
} else {
|
321
|
+
snapshot._error_message = event.target.statusText || "Unknown error";
|
322
|
+
return snapshot._upload_fail();
|
323
|
+
}
|
324
|
+
};
|
325
|
+
xhr = new XMLHttpRequest();
|
326
|
+
xhr.open('POST', api_url);
|
327
|
+
xhr.timeout = timeout;
|
328
|
+
if (csrf_token) {
|
329
|
+
xhr.setRequestHeader("X-CSRF-Token", csrf_token);
|
330
|
+
}
|
331
|
+
xhr.onload = handler;
|
332
|
+
xhr.onerror = handler;
|
333
|
+
xhr.onabort = handler;
|
334
|
+
xhr.send(snapshot._jpeg_blob);
|
335
|
+
return snapshot._xhr = xhr;
|
336
|
+
} else {
|
337
|
+
this._debug("Generating JPEG file");
|
338
|
+
if (snapshot._mirror) {
|
339
|
+
canvas = document.createElement("canvas");
|
340
|
+
canvas.width = snapshot._canvas.width;
|
341
|
+
canvas.height = snapshot._canvas.height;
|
342
|
+
context = canvas.getContext("2d");
|
343
|
+
context.setTransform(1, 0, 0, 1, 0, 0);
|
344
|
+
context.translate(canvas.width, 0);
|
345
|
+
context.scale(-1, 1);
|
346
|
+
context.drawImage(snapshot._canvas, 0, 0);
|
347
|
+
} else {
|
348
|
+
canvas = snapshot._canvas;
|
349
|
+
}
|
350
|
+
return canvas.toBlob(function(blob) {
|
351
|
+
snapshot._jpeg_blob = blob;
|
352
|
+
return that._engine_upload(snapshot, api_url, csrf_token, timeout);
|
353
|
+
}, "image/jpeg", this.quality);
|
354
|
+
}
|
355
|
+
};
|
356
|
+
|
357
|
+
JpegCameraHtml5.prototype._remove_message = function() {
|
358
|
+
return this.message.style.display = "none";
|
359
|
+
};
|
360
|
+
|
361
|
+
JpegCameraHtml5.prototype._load_shutter_sound = function() {
|
362
|
+
var request, that;
|
363
|
+
if (this.audio_context) {
|
364
|
+
return;
|
365
|
+
}
|
366
|
+
this.audio_context = new AudioContext();
|
367
|
+
request = new XMLHttpRequest();
|
368
|
+
request.open('GET', this.options.shutter_url, true);
|
369
|
+
request.responseType = 'arraybuffer';
|
370
|
+
that = this;
|
371
|
+
request.onload = function() {
|
372
|
+
return that.audio_context.decodeAudioData(request.response, function(buffer) {
|
373
|
+
return that.shutter_buffer = buffer;
|
374
|
+
});
|
375
|
+
};
|
376
|
+
return request.send();
|
377
|
+
};
|
378
|
+
|
379
|
+
JpegCameraHtml5.prototype._wait_for_video_ready = function() {
|
380
|
+
var crop, that, video_height, video_width;
|
381
|
+
video_width = parseInt(this.video.videoWidth);
|
382
|
+
video_height = parseInt(this.video.videoHeight);
|
383
|
+
if (video_width > 0 && video_height > 0) {
|
384
|
+
this.video_container.appendChild(this.video);
|
385
|
+
this.video_width = video_width;
|
386
|
+
this.video_height = video_height;
|
387
|
+
this._debug("Camera resolution " + this.video_width + "x" + this.video_height + "px");
|
388
|
+
crop = this._get_video_crop();
|
389
|
+
this.video.style.position = "relative";
|
390
|
+
this.video.style.width = "" + crop.width + "px";
|
391
|
+
this.video.style.height = "" + crop.height + "px";
|
392
|
+
this.video.style.left = "" + crop.x_offset + "px";
|
393
|
+
this.video.style.top = "" + crop.y_offset + "px";
|
394
|
+
return this._prepared();
|
395
|
+
} else if (this._status_checks_count > 100) {
|
396
|
+
return this._got_error("Camera failed to initialize in 10 seconds");
|
397
|
+
} else {
|
398
|
+
this._status_checks_count++;
|
399
|
+
that = this;
|
400
|
+
return setTimeout((function() {
|
401
|
+
return that._wait_for_video_ready();
|
402
|
+
}), 100);
|
403
|
+
}
|
404
|
+
};
|
405
|
+
|
406
|
+
JpegCameraHtml5.prototype._status_checks_count = 0;
|
407
|
+
|
408
|
+
JpegCameraHtml5.prototype._add_prefixed_style = function(element, style, value) {
|
409
|
+
var uppercase_style;
|
410
|
+
uppercase_style = style.charAt(0).toUpperCase() + style.slice(1);
|
411
|
+
element.style[style] = value;
|
412
|
+
element.style["Webkit" + uppercase_style] = value;
|
413
|
+
element.style["Moz" + uppercase_style] = value;
|
414
|
+
element.style["ms" + uppercase_style] = value;
|
415
|
+
return element.style["O" + uppercase_style] = value;
|
416
|
+
};
|
417
|
+
|
418
|
+
JpegCameraHtml5.prototype._get_video_crop = function() {
|
419
|
+
var scaled_video_height, scaled_video_width, video_ratio, video_scale, view_height, view_ratio, view_width;
|
420
|
+
view_width = this._view_width();
|
421
|
+
view_height = this._view_height();
|
422
|
+
video_ratio = this.video_width / this.video_height;
|
423
|
+
view_ratio = view_width / view_height;
|
424
|
+
if (video_ratio >= view_ratio) {
|
425
|
+
this._debug("Filling height");
|
426
|
+
video_scale = view_height / this.video_height;
|
427
|
+
scaled_video_width = Math.round(this.video_width * video_scale);
|
428
|
+
return {
|
429
|
+
width: scaled_video_width,
|
430
|
+
height: view_height,
|
431
|
+
x_offset: -Math.floor((scaled_video_width - view_width) / 2.0),
|
432
|
+
y_offset: 0
|
433
|
+
};
|
434
|
+
} else {
|
435
|
+
this._debug("Filling width");
|
436
|
+
video_scale = view_width / this.video_width;
|
437
|
+
scaled_video_height = Math.round(this.video_height * video_scale);
|
438
|
+
return {
|
439
|
+
width: view_width,
|
440
|
+
height: scaled_video_height,
|
441
|
+
x_offset: 0,
|
442
|
+
y_offset: -Math.floor((scaled_video_height - view_height) / 2.0)
|
443
|
+
};
|
444
|
+
}
|
445
|
+
};
|
446
|
+
|
447
|
+
JpegCameraHtml5.prototype._get_capture_crop = function() {
|
448
|
+
var snapshot_height, snapshot_width, video_ratio, view_height, view_ratio, view_width;
|
449
|
+
view_width = this._view_width();
|
450
|
+
view_height = this._view_height();
|
451
|
+
video_ratio = this.video_width / this.video_height;
|
452
|
+
view_ratio = view_width / view_height;
|
453
|
+
if (video_ratio >= view_ratio) {
|
454
|
+
snapshot_width = Math.round(this.video_height * view_ratio);
|
455
|
+
return {
|
456
|
+
width: snapshot_width,
|
457
|
+
height: this.video_height,
|
458
|
+
x_offset: Math.floor((this.video_width - snapshot_width) / 2.0),
|
459
|
+
y_offset: 0
|
460
|
+
};
|
461
|
+
} else {
|
462
|
+
snapshot_height = Math.round(this.video_width / view_ratio);
|
463
|
+
return {
|
464
|
+
width: this.video_width,
|
465
|
+
height: snapshot_height,
|
466
|
+
x_offset: 0,
|
467
|
+
y_offset: Math.floor((this.video_height - snapshot_height) / 2.0)
|
468
|
+
};
|
469
|
+
}
|
470
|
+
};
|
471
|
+
|
472
|
+
return JpegCameraHtml5;
|
473
|
+
|
474
|
+
})(JpegCamera);
|
475
|
+
({
|
476
|
+
video_width: null,
|
477
|
+
video_height: null
|
478
|
+
});
|
479
|
+
window.JpegCamera = JpegCameraHtml5;
|
480
|
+
}
|
481
|
+
|
482
|
+
supported_flash_version = '9';
|
483
|
+
|
484
|
+
if (!window.JpegCamera && window.swfobject && swfobject.hasFlashPlayerVersion(supported_flash_version)) {
|
485
|
+
JpegCameraFlash = (function(_super) {
|
486
|
+
__extends(JpegCameraFlash, _super);
|
487
|
+
|
488
|
+
function JpegCameraFlash() {
|
489
|
+
_ref1 = JpegCameraFlash.__super__.constructor.apply(this, arguments);
|
490
|
+
return _ref1;
|
491
|
+
}
|
492
|
+
|
493
|
+
JpegCameraFlash._send_message = function(id, method) {
|
494
|
+
var args, instance;
|
495
|
+
instance = this._instances[parseInt(id)];
|
496
|
+
if (!instance) {
|
497
|
+
return;
|
498
|
+
}
|
499
|
+
args = Array.prototype.slice.call(arguments, 2);
|
500
|
+
return this.prototype[method].apply(instance, args);
|
501
|
+
};
|
502
|
+
|
503
|
+
JpegCameraFlash._instances = {};
|
504
|
+
|
505
|
+
JpegCameraFlash._next_id = 1;
|
506
|
+
|
507
|
+
JpegCameraFlash.prototype._engine_init = function() {
|
508
|
+
var attributes, callback, flash_object_id, flashvars, height, params, that, width;
|
509
|
+
this._debug("Using Flash engine");
|
510
|
+
this._id = this.constructor._next_id++;
|
511
|
+
this.constructor._instances[this._id] = this;
|
512
|
+
width = this._view_width();
|
513
|
+
height = this._view_height();
|
514
|
+
if (width < 215 || height < 138) {
|
515
|
+
this._got_error("camera is too small to display privacy dialog");
|
516
|
+
return;
|
517
|
+
}
|
518
|
+
flash_object_id = "flash_object_" + this._id;
|
519
|
+
params = {
|
520
|
+
loop: "false",
|
521
|
+
allowScriptAccess: "always",
|
522
|
+
allowFullScreen: "false",
|
523
|
+
quality: "best",
|
524
|
+
wmode: "opaque",
|
525
|
+
menu: "false"
|
526
|
+
};
|
527
|
+
attributes = {
|
528
|
+
id: flash_object_id,
|
529
|
+
align: "middle"
|
530
|
+
};
|
531
|
+
flashvars = {
|
532
|
+
id: this._id,
|
533
|
+
width: width,
|
534
|
+
height: height,
|
535
|
+
shutter_url: this.options.shutter_url
|
536
|
+
};
|
537
|
+
that = this;
|
538
|
+
callback = function(event) {
|
539
|
+
if (!event.success) {
|
540
|
+
return that._got_error("Flash loading failed.");
|
541
|
+
} else {
|
542
|
+
that._debug("Flash loaded");
|
543
|
+
return that._flash = document.getElementById(flash_object_id);
|
544
|
+
}
|
545
|
+
};
|
546
|
+
this.internal_container = document.createElement("div");
|
547
|
+
this.internal_container.id = "jpeg_camera_flash_" + this._id;
|
548
|
+
this.internal_container.style.width = "100%";
|
549
|
+
this.internal_container.style.height = "100%";
|
550
|
+
this.container.appendChild(this.internal_container);
|
551
|
+
return swfobject.embedSWF(this.options.swf_url, this.internal_container.id, width, height, '9', null, flashvars, params, attributes, callback);
|
552
|
+
};
|
553
|
+
|
554
|
+
JpegCameraFlash.prototype._engine_play_shutter_sound = function() {
|
555
|
+
return this._flash._play_shutter();
|
556
|
+
};
|
557
|
+
|
558
|
+
JpegCameraFlash.prototype._engine_capture = function(snapshot, mirror, quality) {
|
559
|
+
return this._flash._capture(snapshot.id, mirror, quality);
|
560
|
+
};
|
561
|
+
|
562
|
+
JpegCameraFlash.prototype._engine_display = function(snapshot) {
|
563
|
+
return this._flash._display(snapshot.id);
|
564
|
+
};
|
565
|
+
|
566
|
+
JpegCameraFlash.prototype._engine_discard = function(snapshot) {
|
567
|
+
return this._flash._discard(snapshot.id);
|
568
|
+
};
|
569
|
+
|
570
|
+
JpegCameraFlash.prototype._engine_show_stream = function() {
|
571
|
+
return this._flash._show_stream();
|
572
|
+
};
|
573
|
+
|
574
|
+
JpegCameraFlash.prototype._engine_upload = function(snapshot, api_url, csrf_token, timeout) {
|
575
|
+
return this._flash._upload(snapshot.id, api_url, csrf_token, timeout);
|
576
|
+
};
|
577
|
+
|
578
|
+
JpegCameraFlash.prototype._flash_prepared = function() {
|
579
|
+
return this._prepared();
|
580
|
+
};
|
581
|
+
|
582
|
+
JpegCameraFlash.prototype._flash_upload_complete = function(snapshot_id, status_code, error, response) {
|
583
|
+
var snapshot;
|
584
|
+
snapshot_id = parseInt(snapshot_id);
|
585
|
+
snapshot = this._snapshots[snapshot_id];
|
586
|
+
snapshot._status = parseInt(status_code);
|
587
|
+
snapshot._response = response;
|
588
|
+
if (snapshot._status >= 200 && snapshot._status < 300) {
|
589
|
+
return snapshot._upload_done();
|
590
|
+
} else {
|
591
|
+
snapshot._error_message = error;
|
592
|
+
return snapshot._upload_fail();
|
593
|
+
}
|
594
|
+
};
|
595
|
+
|
596
|
+
return JpegCameraFlash;
|
597
|
+
|
598
|
+
})(JpegCamera);
|
599
|
+
window.JpegCamera = JpegCameraFlash;
|
600
|
+
}
|
601
|
+
|
602
|
+
Snapshot = (function() {
|
603
|
+
Snapshot._next_snapshot_id = 1;
|
604
|
+
|
605
|
+
function Snapshot(camera, options) {
|
606
|
+
this.camera = camera;
|
607
|
+
this.options = options;
|
608
|
+
this.id = this.constructor._next_snapshot_id++;
|
609
|
+
}
|
610
|
+
|
611
|
+
Snapshot.prototype._discarded = false;
|
612
|
+
|
613
|
+
Snapshot.prototype.show = function() {
|
614
|
+
if (this._discarded) {
|
615
|
+
raise("discarded snapshot cannot be used");
|
616
|
+
}
|
617
|
+
this.camera._display(this);
|
618
|
+
return this;
|
619
|
+
};
|
620
|
+
|
621
|
+
Snapshot.prototype.hide = function() {
|
622
|
+
if (this.camera.displayed_snapshot() === this) {
|
623
|
+
this.camera.show_stream();
|
624
|
+
}
|
625
|
+
return this;
|
626
|
+
};
|
627
|
+
|
628
|
+
Snapshot.prototype.upload = function(options) {
|
629
|
+
var cache, csrf_token;
|
630
|
+
if (options == null) {
|
631
|
+
options = {};
|
632
|
+
}
|
633
|
+
if (this._discarded) {
|
634
|
+
raise("discarded snapshot cannot be used");
|
635
|
+
}
|
636
|
+
if (this._uploading) {
|
637
|
+
this._debug("Upload already in progress");
|
638
|
+
return;
|
639
|
+
}
|
640
|
+
this._uploading = true;
|
641
|
+
this._upload_options = options;
|
642
|
+
cache = this._options();
|
643
|
+
if (!cache.api_url) {
|
644
|
+
this.camera._debug("Snapshot#upload called without valid api_url");
|
645
|
+
throw "Snapshot#upload called without valid api_url";
|
646
|
+
}
|
647
|
+
if ("string" === typeof cache.csrf_token && cache.csrf_token.length > 0) {
|
648
|
+
csrf_token = cache.csrf_token;
|
649
|
+
} else {
|
650
|
+
csrf_token = null;
|
651
|
+
}
|
652
|
+
this._done = false;
|
653
|
+
this._response = null;
|
654
|
+
this._fail = false;
|
655
|
+
this._status = null;
|
656
|
+
this._error_message = null;
|
657
|
+
this.camera._upload(this, cache.api_url, csrf_token, cache.timeout);
|
658
|
+
return this;
|
659
|
+
};
|
660
|
+
|
661
|
+
Snapshot.prototype._upload_options = {};
|
662
|
+
|
663
|
+
Snapshot.prototype._uploading = false;
|
664
|
+
|
665
|
+
Snapshot.prototype.done = function(callback) {
|
666
|
+
var cache;
|
667
|
+
if (this._discarded) {
|
668
|
+
raise("discarded snapshot cannot be used");
|
669
|
+
}
|
670
|
+
this._upload_options.on_upload_done = callback;
|
671
|
+
cache = this._options();
|
672
|
+
if (cache.on_upload_done && this._done) {
|
673
|
+
cache.on_upload_done.call(this, this._response);
|
674
|
+
}
|
675
|
+
return this;
|
676
|
+
};
|
677
|
+
|
678
|
+
Snapshot.prototype._done = false;
|
679
|
+
|
680
|
+
Snapshot.prototype._response = null;
|
681
|
+
|
682
|
+
Snapshot.prototype.fail = function(callback) {
|
683
|
+
var cache;
|
684
|
+
if (this._discarded) {
|
685
|
+
raise("discarded snapshot cannot be used");
|
686
|
+
}
|
687
|
+
this._upload_options.on_upload_fail = callback;
|
688
|
+
cache = this._options();
|
689
|
+
if (cache.on_upload_fail && this._fail) {
|
690
|
+
cache.on_upload_fail.call(this, this._status, this._error_message, this._response);
|
691
|
+
}
|
692
|
+
return this;
|
693
|
+
};
|
694
|
+
|
695
|
+
Snapshot.prototype._fail = false;
|
696
|
+
|
697
|
+
Snapshot.prototype._status = null;
|
698
|
+
|
699
|
+
Snapshot.prototype._error_message = null;
|
700
|
+
|
701
|
+
Snapshot.prototype.discard = function() {
|
702
|
+
this.camera._discard(this);
|
703
|
+
return void 0;
|
704
|
+
};
|
705
|
+
|
706
|
+
Snapshot.prototype._options = function() {
|
707
|
+
return this.camera._extend({}, this.camera.options, this.options, this._upload_options);
|
708
|
+
};
|
709
|
+
|
710
|
+
Snapshot.prototype._upload_done = function() {
|
711
|
+
var cache;
|
712
|
+
this.camera._debug("Upload completed");
|
713
|
+
this._uploading = false;
|
714
|
+
this._done = true;
|
715
|
+
cache = this._options();
|
716
|
+
if (cache.on_upload_done) {
|
717
|
+
return cache.on_upload_done.call(this, this._response);
|
718
|
+
}
|
719
|
+
};
|
720
|
+
|
721
|
+
Snapshot.prototype._upload_fail = function() {
|
722
|
+
var cache;
|
723
|
+
this.camera._debug("Upload failed with status " + this._status);
|
724
|
+
this._uploading = false;
|
725
|
+
this._fail = true;
|
726
|
+
cache = this._options();
|
727
|
+
if (cache.on_upload_fail) {
|
728
|
+
return cache.on_upload_fail.call(this, this._status, this._error_message, this._response);
|
729
|
+
}
|
730
|
+
};
|
731
|
+
|
732
|
+
return Snapshot;
|
733
|
+
|
734
|
+
})();
|
735
|
+
|
736
|
+
}).call(this);
|