active_scaffold_camera 0.1.0 → 0.2.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6d2dd4e1f852c81a0a90e6b77b0db2fdf259a974843c907e059283bcc0b251be
|
|
4
|
+
data.tar.gz: 01eeb04a95ba9e38326e0038e203019b521342f8b5a1b3803d12f00995e511d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 320c8a9a6e429e0155a31823db685ef430e4eabe806641ba2f856ed942a06e253cfdd1614a09c2cd0d58b1ba6c413902eb0989123bd8799edf988b31514a6761
|
|
7
|
+
data.tar.gz: 9ad5a523b0f1b902f5d33f35a15e5c5a9cfbb2e18ca9313f5a2ae3d04d655f325f65e471acbd41d585ea1b179a61a7ea8c6da2eb6ecb3fd3541a37e2abe17e29
|
|
@@ -1,39 +1,48 @@
|
|
|
1
|
-
|
|
1
|
+
# Camera for ActiveScaffold
|
|
2
2
|
|
|
3
3
|
Currently, this plugin is compatible with ActiveScaffold >= 3.4 gem.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
This plugin adds a camera viewer to take a snapshot from camera on ActiveScaffold forms. It uses
|
|
7
|
+
This plugin adds a camera viewer to take a snapshot from camera on ActiveScaffold forms. It uses [SayCheese.js](https://github.com/leemachin/say-cheese)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### Browser compatibility
|
|
10
|
+
|
|
11
|
+
The plugin uses the modern `navigator.mediaDevices` API when available, including
|
|
12
|
+
[`enumerateDevices()`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices)
|
|
13
|
+
and `deviceId` constraints. The legacy callback-based API, `MediaStreamTrack.getSources`,
|
|
14
|
+
and `sourceId` constraints remain available as a fallback for older browsers.
|
|
15
|
+
|
|
16
|
+
Camera access requires a secure context (HTTPS or localhost) and the user's permission.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
10
19
|
|
|
11
20
|
You'll need at least ActiveScaffold 3.4 to use this
|
|
12
21
|
|
|
13
|
-
|
|
22
|
+
```
|
|
14
23
|
gem install active_scaffold_camera
|
|
15
|
-
|
|
24
|
+
```
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
## Usage
|
|
18
27
|
|
|
19
|
-
|
|
28
|
+
#### Step 1
|
|
20
29
|
|
|
21
30
|
Set column to use :snapshot form_ui
|
|
22
31
|
|
|
23
|
-
|
|
32
|
+
#### Step 2
|
|
24
33
|
|
|
25
34
|
Setup snapshot using options method on column
|
|
26
35
|
|
|
27
|
-
|
|
36
|
+
```ruby
|
|
28
37
|
# app/controllers/visitors_controller.rb
|
|
29
38
|
|
|
30
39
|
class VisitorsController < ApplicationController
|
|
31
40
|
active_scaffold :visitor do |config|
|
|
32
|
-
config.columns[:
|
|
33
|
-
config.columns[:
|
|
41
|
+
config.columns[:id_card].form_ui = :snapshot
|
|
42
|
+
config.columns[:id_card].options = {:source => -1}
|
|
34
43
|
end
|
|
35
44
|
end
|
|
36
|
-
|
|
45
|
+
```
|
|
37
46
|
|
|
38
47
|
Available options: video_not_supported, audio_not_supported, media_forbidden, source
|
|
39
48
|
|
|
@@ -41,20 +50,20 @@ Source can be set to use a specific source instead of displaying source selector
|
|
|
41
50
|
|
|
42
51
|
If video_not_supported, audio_not_supported or media_forbidden are symbols they will be translated (using as_ method, so it must be on active_scaffold namespace). They have a default translation.
|
|
43
52
|
|
|
44
|
-
|
|
53
|
+
#### Save image
|
|
45
54
|
|
|
46
55
|
Snapshot form_ui sends a data url, encoded on base64, of the image, so it should be saved on column of blob type.
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
## Support
|
|
49
58
|
|
|
50
|
-
If you have issues installing the plugin, search / post to the
|
|
59
|
+
If you have issues installing the plugin, search / post to the [Active Scaffold](http://groups.google.com/group/activescaffold) forum or [Create an issue](http://github.com/activescaffold/active_scaffold_camera/issues)
|
|
51
60
|
|
|
52
|
-
|
|
61
|
+
## Contributing
|
|
53
62
|
|
|
54
63
|
Fork, hack, push, and request a pull:
|
|
55
64
|
|
|
56
65
|
http://github.com/activescaffold/active_scaffold_camera/
|
|
57
66
|
|
|
58
|
-
|
|
67
|
+
## License
|
|
59
68
|
|
|
60
69
|
Released under the MIT license (included).
|
|
@@ -2,12 +2,40 @@
|
|
|
2
2
|
//= require_self
|
|
3
3
|
|
|
4
4
|
ActiveScaffold.snapshot = function(selector_or_elements, parent) {
|
|
5
|
+
function modernMediaApi() {
|
|
6
|
+
return navigator.mediaDevices && navigator.mediaDevices.getUserMedia;
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
function videoConstraint(video) {
|
|
6
|
-
|
|
10
|
+
if (typeof(video) != 'string') return video;
|
|
11
|
+
return modernMediaApi() ? {deviceId: {exact: video}} : {optional: [{sourceId: video}]};
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
function audioConstraint(audio) {
|
|
10
|
-
|
|
15
|
+
if (typeof(audio) != 'string') return audio;
|
|
16
|
+
return modernMediaApi() ? {deviceId: {exact: audio}} : {optional: [{sourceId: audio}]};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function enumerateVideoSources(callback) {
|
|
20
|
+
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
|
|
21
|
+
navigator.mediaDevices.enumerateDevices().then(function(devices) {
|
|
22
|
+
callback(devices.filter(function(device) {
|
|
23
|
+
return device.kind == 'videoinput';
|
|
24
|
+
}).map(function(device) {
|
|
25
|
+
return {id: device.deviceId, label: device.label};
|
|
26
|
+
}));
|
|
27
|
+
}).catch(function() {
|
|
28
|
+
callback([]);
|
|
29
|
+
});
|
|
30
|
+
} else if (window.MediaStreamTrack && MediaStreamTrack.getSources) {
|
|
31
|
+
MediaStreamTrack.getSources(function(sourceInfos) {
|
|
32
|
+
callback(sourceInfos.filter(function(source) {
|
|
33
|
+
return source.kind == 'video';
|
|
34
|
+
}));
|
|
35
|
+
});
|
|
36
|
+
} else {
|
|
37
|
+
callback([]);
|
|
38
|
+
}
|
|
11
39
|
}
|
|
12
40
|
|
|
13
41
|
function startVideo(element, video, audio, video_select) {
|
|
@@ -59,22 +87,15 @@ ActiveScaffold.snapshot = function(selector_or_elements, parent) {
|
|
|
59
87
|
|
|
60
88
|
elements.each(function() {
|
|
61
89
|
var $element = $(this), selector = '#' + $element.attr('id');
|
|
62
|
-
|
|
63
|
-
var sources = [];
|
|
64
|
-
for(i in sourceInfos) {
|
|
65
|
-
var source = sourceInfos[i];
|
|
66
|
-
if (source.kind == 'video') {
|
|
67
|
-
sources.push(source);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
90
|
+
enumerateVideoSources(function(sources) {
|
|
70
91
|
var video, source, select, index = $element.data('source');
|
|
71
92
|
if (index != null) {
|
|
72
93
|
if (index < 0) source = sources[sources.length + index];
|
|
73
94
|
else source = sources[index];
|
|
74
95
|
if (source) video = source.id;
|
|
75
96
|
} else if (sources.length > 1) {
|
|
76
|
-
|
|
77
|
-
for (i in sources) {
|
|
97
|
+
select = $('<select>');
|
|
98
|
+
for (var i in sources) {
|
|
78
99
|
source = sources[i];
|
|
79
100
|
select.append($('<option>').val(source.id).html(source.label || 'camera ' + (i + 1)));
|
|
80
101
|
}
|
|
@@ -16,7 +16,7 @@ var SayCheese = (function() {
|
|
|
16
16
|
|
|
17
17
|
var SayCheese;
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
var legacyGetUserMedia = (navigator.getUserMedia ||
|
|
20
20
|
navigator.webkitGetUserMedia ||
|
|
21
21
|
navigator.mozGetUserMedia ||
|
|
22
22
|
navigator.msGetUserMedia ||
|
|
@@ -89,6 +89,8 @@ var SayCheese = (function() {
|
|
|
89
89
|
streaming = false;
|
|
90
90
|
|
|
91
91
|
this.video = document.createElement('video');
|
|
92
|
+
this.video.autoplay = true;
|
|
93
|
+
this.video.playsInline = true;
|
|
92
94
|
|
|
93
95
|
this.video.addEventListener('canplay', function() {
|
|
94
96
|
if (!streaming) {
|
|
@@ -137,7 +139,7 @@ var SayCheese = (function() {
|
|
|
137
139
|
SayCheese.prototype.start = function start() {
|
|
138
140
|
|
|
139
141
|
// fail fast and softly if browser not supported
|
|
140
|
-
if (navigator.getUserMedia === false) {
|
|
142
|
+
if ((!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) && legacyGetUserMedia === false) {
|
|
141
143
|
this.trigger('error', 'NOT_SUPPORTED');
|
|
142
144
|
return false;
|
|
143
145
|
}
|
|
@@ -146,7 +148,9 @@ var SayCheese = (function() {
|
|
|
146
148
|
this.stream = stream;
|
|
147
149
|
this.createVideo();
|
|
148
150
|
|
|
149
|
-
if (
|
|
151
|
+
if ('srcObject' in this.video) {
|
|
152
|
+
this.video.srcObject = stream;
|
|
153
|
+
} else if (navigator.mozGetUserMedia) {
|
|
150
154
|
this.video.mozSrcObject = stream;
|
|
151
155
|
} else {
|
|
152
156
|
this.video.src = this.getStreamUrl();
|
|
@@ -169,16 +173,36 @@ var SayCheese = (function() {
|
|
|
169
173
|
this.trigger('error', error);
|
|
170
174
|
}.bind(this);
|
|
171
175
|
|
|
172
|
-
|
|
176
|
+
var constraints = { video: this.options.video, audio: this.options.audio };
|
|
177
|
+
|
|
178
|
+
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
|
179
|
+
return navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return legacyGetUserMedia.call(navigator, constraints, success, error);
|
|
173
183
|
};
|
|
174
184
|
|
|
175
185
|
SayCheese.prototype.stop = function stop() {
|
|
176
|
-
this.stream
|
|
186
|
+
if (!this.stream) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (this.stream.getTracks) {
|
|
191
|
+
this.stream.getTracks().forEach(function(track) {
|
|
192
|
+
track.stop();
|
|
193
|
+
});
|
|
194
|
+
} else if (this.stream.stop) {
|
|
195
|
+
this.stream.stop();
|
|
196
|
+
}
|
|
177
197
|
|
|
178
|
-
if (
|
|
198
|
+
if (this.video && 'srcObject' in this.video) {
|
|
199
|
+
this.video.srcObject = null;
|
|
200
|
+
} else if (this.video && window.URL && window.URL.revokeObjectURL && this.video.src) {
|
|
179
201
|
window.URL.revokeObjectURL(this.video.src);
|
|
180
202
|
}
|
|
181
203
|
|
|
204
|
+
this.stream = null;
|
|
205
|
+
|
|
182
206
|
return this.trigger('stop');
|
|
183
207
|
};
|
|
184
208
|
|
metadata
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_scaffold_camera
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sergio Cambra
|
|
8
8
|
- Volker Hochstein
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: bundler
|
|
@@ -46,10 +45,10 @@ executables: []
|
|
|
46
45
|
extensions: []
|
|
47
46
|
extra_rdoc_files:
|
|
48
47
|
- LICENSE
|
|
49
|
-
- README.
|
|
48
|
+
- README.md
|
|
50
49
|
files:
|
|
51
50
|
- LICENSE
|
|
52
|
-
- README.
|
|
51
|
+
- README.md
|
|
53
52
|
- app/assets/javascripts/active_scaffold_camera.js
|
|
54
53
|
- app/assets/javascripts/say-cheese.js
|
|
55
54
|
- app/assets/stylesheets/active_scaffold_camera.scss
|
|
@@ -63,7 +62,6 @@ homepage: http://github.com/activescaffold/active_scaffold_camera
|
|
|
63
62
|
licenses:
|
|
64
63
|
- MIT
|
|
65
64
|
metadata: {}
|
|
66
|
-
post_install_message:
|
|
67
65
|
rdoc_options: []
|
|
68
66
|
require_paths:
|
|
69
67
|
- lib
|
|
@@ -78,8 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
78
76
|
- !ruby/object:Gem::Version
|
|
79
77
|
version: '0'
|
|
80
78
|
requirements: []
|
|
81
|
-
rubygems_version: 3.
|
|
82
|
-
signing_key:
|
|
79
|
+
rubygems_version: 3.6.9
|
|
83
80
|
specification_version: 4
|
|
84
81
|
summary: Snapshot form_ui using saycheese.js
|
|
85
82
|
test_files: []
|