jpeg_camera 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|