Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
rclnodejs-testing
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Oleg Dzhimiev
rclnodejs-testing
Commits
cfcf6b51
Commit
cfcf6b51
authored
Jan 29, 2019
by
Oleg Dzhimiev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1. read pars
2. set pars 3. implementing snapshot downloading of all images by ts
parent
aa7f8618
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
374 additions
and
53 deletions
+374
-53
e393.js
public/javascripts/e393.js
+11
-4
index.js
public/javascripts/index.js
+217
-48
snapshot.js
public/javascripts/snapshot.js
+141
-0
style.css
public/stylesheets/style.css
+5
-1
No files found.
public/javascripts/e393.js
View file @
cfcf6b51
...
@@ -72,10 +72,12 @@ class E393_Port {
...
@@ -72,10 +72,12 @@ class E393_Port {
// update timestamps
// update timestamps
update_timestamps
(
ts
){
update_timestamps
(
ts
){
let
self
=
this
;
let
self
=
this
;
this
.
_data
.
timestamps
=
[];
// line below breaks references to this._data.timestamps variable:
//this._data.timestamps = [];
// so, as suggested here:
// https://stackoverflow.com/questions/1232040/how-do-i-empty-an-array-in-javascript
this
.
_data
.
timestamps
.
length
=
0
;
$
(
ts
).
children
().
each
(
function
(){
$
(
ts
).
children
().
each
(
function
(){
self
.
_data
.
timestamps
.
push
({
self
.
_data
.
timestamps
.
push
({
frame
:
parseInt
(
$
(
this
).
attr
(
"frame"
)),
frame
:
parseInt
(
$
(
this
).
attr
(
"frame"
)),
...
@@ -83,7 +85,6 @@ class E393_Port {
...
@@ -83,7 +85,6 @@ class E393_Port {
ptr
:
parseInt
(
$
(
this
).
attr
(
"ptr"
)),
ptr
:
parseInt
(
$
(
this
).
attr
(
"ptr"
)),
});
});
});
});
}
}
}
}
...
@@ -94,6 +95,7 @@ class E393 {
...
@@ -94,6 +95,7 @@ class E393 {
constructor
(
options
){
constructor
(
options
){
let
defaults
=
{
let
defaults
=
{
ip
:
"0.0.0.0"
,
master_port
:
"N/A"
,
master_port
:
"N/A"
,
systime
:
""
,
systime
:
""
,
systimestamp
:
0
,
systimestamp
:
0
,
...
@@ -119,6 +121,9 @@ class E393 {
...
@@ -119,6 +121,9 @@ class E393 {
this
.
_data
=
$
.
extend
(
defaults
,{});
this
.
_data
=
$
.
extend
(
defaults
,{});
this
.
_data
.
ip
=
$
(
options
).
find
(
"camera"
).
attr
(
"ip"
);
// bchn is for multi-cams and imgsrv
this
.
_data
.
bchn
=
$
(
options
).
find
(
"camera"
).
attr
(
"bchn"
);
this
.
_data
.
master_port
=
parseInt
(
$
(
options
).
find
(
"master_port"
).
text
());
this
.
_data
.
master_port
=
parseInt
(
$
(
options
).
find
(
"master_port"
).
text
());
this
.
_data
.
systime
=
$
(
options
).
find
(
"systime"
).
text
();
this
.
_data
.
systime
=
$
(
options
).
find
(
"systime"
).
text
();
this
.
_data
.
systimestamp
=
$
(
options
).
find
(
"systimestamp"
).
text
();
this
.
_data
.
systimestamp
=
$
(
options
).
find
(
"systimestamp"
).
text
();
...
@@ -143,6 +148,8 @@ class E393 {
...
@@ -143,6 +148,8 @@ class E393 {
this
.
_data
=
$
.
extend
(
defaults
,
options
);
this
.
_data
=
$
.
extend
(
defaults
,
options
);
}
}
this
.
ip
=
this
.
_data
.
ip
;
this
.
bchn
=
this
.
_data
.
bchn
;
this
.
master_port
=
this
.
_data
.
master_port
;
this
.
master_port
=
this
.
_data
.
master_port
;
this
.
systime
=
this
.
_data
.
systime
;
this
.
systime
=
this
.
_data
.
systime
;
this
.
systimestamp
=
this
.
_data
.
systimestamp
;
this
.
systimestamp
=
this
.
_data
.
systimestamp
;
...
...
public/javascripts/index.js
View file @
cfcf6b51
...
@@ -21,13 +21,34 @@ let Cams = [];
...
@@ -21,13 +21,34 @@ let Cams = [];
async
function
a_init
(){
async
function
a_init
(){
let
res
;
const
url_set_master
=
parse_url
();
if
(
url_set_master
)
{
await
a_deep_init
();
console
.
log
(
"Done"
);
}
else
{
console
.
log
(
"Master node is not selected (in url string). Call 'List master'"
);
}
}
async
function
a_deep_init
(){
// reset everything
$
(
"#nodelist"
).
empty
();
$
(
"#slavenodes"
).
empty
();
appData
.
slaves
=
[];
appData
.
ips
=
[];
appData
.
slaves_selected
=
[];
// url
let
res
;
res
=
await
a_parse_url
();
// get ips
res
=
await
a_send_command
(
'ifconfig'
,
appData
.
slaves
);
parse_cmd_ifconfig_init
(
res
);
parse_cmd_ifconfig_init
(
res
);
// detect
// identify
res
=
await
a_detect_10393s
();
res
=
await
a_detect_10393s
();
parse_detect_10393s
(
res
);
parse_detect_10393s
(
res
);
...
@@ -37,7 +58,6 @@ async function a_init(){
...
@@ -37,7 +58,6 @@ async function a_init(){
// update interface
// update interface
update_ui
();
update_ui
();
console
.
log
(
"Done"
);
}
}
...
@@ -60,14 +80,14 @@ function update_ui(){
...
@@ -60,14 +80,14 @@ function update_ui(){
pars
[
p
]
=
tmp
;
pars
[
p
]
=
tmp
;
// this is an exclusion
// this is an exclusion
// TODO: fix and remove later
// TODO: fix and remove later
}
else
if
(
pars
[
p
]
===
1
){
}
else
if
(
(
pars
[
p
]
===
1
)
&&
(
p
===
"trig_period"
)
){
pars
[
p
]
=
tmp
;
pars
[
p
]
=
tmp
;
// after init
// after init
}
else
{
}
else
{
// not all are "none"
// not all are "none"
if
(
!
Cams
[
i
].
ports
[
j
].
sensor
.
every
(
v
=>
v
===
"none"
)){
if
(
!
Cams
[
i
].
ports
[
j
].
sensor
.
every
(
v
=>
v
===
"none"
)){
// comparing init to others
// comparing init to others
if
((
pars
[
p
]
!==
tmp
)
&&
(
tmp
!==
1
)){
if
((
pars
[
p
]
!==
tmp
)
&&
(
tmp
!==
1
)
&&
(
p
!==
"trig_period"
)
){
console
.
log
(
"Warning! "
+
p
+
" is not the same across all cameras/ports"
);
console
.
log
(
"Warning! "
+
p
+
" is not the same across all cameras/ports"
);
}
}
}
}
...
@@ -84,9 +104,32 @@ function update_ui(){
...
@@ -84,9 +104,32 @@ function update_ui(){
$
(
"#set_quality .input-par"
).
val
(
quality
);
$
(
"#set_quality .input-par"
).
val
(
quality
);
$
(
"#set_fps .input-par"
).
val
(
fps
);
$
(
"#set_fps .input-par"
).
val
(
fps
);
console
.
log
(
"White balance is "
+
pars
.
wb_en
);
button_switch
(
$
(
'#toggle_awb'
)
,
pars
.
wb_en
);
button_switch
(
$
(
'#toggle_awb'
)
,
pars
.
wb_en
);
button_switch
(
$
(
'#toggle_aexp'
),
pars
.
autoexp_on
);
button_switch
(
$
(
'#toggle_aexp'
),
pars
.
autoexp_on
);
// onchange
$
(
"#set_format .input-par"
).
change
(
function
(){
let
fmt
=
format_str2num
(
$
(
this
).
val
());
a_set_params
({
COLOR
:
fmt
}).
then
(()
=>
{
console
.
log
(
"format set"
);
});
});
$
(
"#set_quality .input-par"
).
change
(
function
(){
a_set_params
({
QUALITY
:
$
(
this
).
val
()}).
then
(()
=>
{
console
.
log
(
"quality set"
);
});
});
$
(
"#set_fps .input-par"
).
change
(
function
(){
let
period
=
fps_fps2period
(
$
(
this
).
val
());
a_set_params
({
TRIG_PERIOD
:
period
}).
then
(()
=>
{
console
.
log
(
"period set"
);
});
});
}
}
function
init
(){
function
init
(){
...
@@ -134,16 +177,8 @@ function init(){
...
@@ -134,16 +177,8 @@ function init(){
update_master_node
(
$
(
this
).
html
());
update_master_node
(
$
(
this
).
html
());
rewrite_url
();
rewrite_url
();
a_deep_init
();
// reset everything
$
(
"#nodelist"
).
empty
();
$
(
"#slavenodes"
).
empty
();
appData
.
slaves
=
[];
appData
.
ips
=
[];
appData
.
slaves_selected
=
[];
// go straight with ifconfig
send_command
(
'ifconfig'
,
appData
.
slaves
,
parse_cmd_ifconfig_init
);
});
});
}
}
...
@@ -191,8 +226,6 @@ function init(){
...
@@ -191,8 +226,6 @@ function init(){
//send_command(cmd, appData.slaves_selected,parse_cmd_testing);
//send_command(cmd, appData.slaves_selected,parse_cmd_testing);
mtest
();
});
});
...
@@ -215,6 +248,24 @@ async function a_read_params(){
...
@@ -215,6 +248,24 @@ async function a_read_params(){
}
}
async
function
a_set_params
(
pars
){
let
ps
=
[];
for
(
let
p
in
pars
){
let
pname
=
p
.
toUpperCase
();
ps
.
push
(
pname
+
"="
+
pars
[
p
]
+
"&*"
+
pname
+
"=0xf"
);
}
let
pstr
=
ps
.
join
(
"&"
);
let
cmd
=
wget_rq
(
"parsedit.php?immediate&sensor_port=0&"
+
pstr
);
//let cmd = wget_rq("diagnostics.php");
let
targets
=
appData
.
slaves_selected
;
let
result
=
await
a_send_command
(
cmd
,
targets
);
return
result
;
}
async
function
a_detect_10393s
(){
async
function
a_detect_10393s
(){
let
targets
=
appData
.
slaves_selected
;
let
targets
=
appData
.
slaves_selected
;
...
@@ -339,6 +390,20 @@ function parse_read_params(res){
...
@@ -339,6 +390,20 @@ function parse_read_params(res){
$
(
"tr."
+
name
+
" .slave_state"
).
html
(
"<b style='color:DarkOrange;'>not 10393</b>"
);
$
(
"tr."
+
name
+
" .slave_state"
).
html
(
"<b style='color:DarkOrange;'>not 10393</b>"
);
}
else
{
}
else
{
if
(
$
(
x
).
find
(
"camera"
).
length
==
1
)
{
if
(
$
(
x
).
find
(
"camera"
).
length
==
1
)
{
// auto assign bchn (for multi cams for imgsrv), at this point as well
let
bchn
=
0
;
if
(
Cams
.
length
!=
0
){
let
c
=
Cams
[
Cams
.
length
-
1
];
bchn
=
c
.
bchn
;
for
(
let
i
=
0
;
i
<
c
.
ports
.
length
;
i
++
){
if
(
c
.
ports
[
i
].
sensor
[
0
]
!=
"none"
){
bchn
++
;
}
}
}
$
(
x
).
find
(
"camera"
).
attr
(
"bchn"
,
bchn
);
$
(
x
).
find
(
"camera"
).
attr
(
"ip"
,
get_ipaddr_by_name
(
name
));
Cams
.
push
(
new
E393
(
x
));
Cams
.
push
(
new
E393
(
x
));
}
}
}
}
...
@@ -637,25 +702,9 @@ function get_ipaddr_from_ifconfig(str){
...
@@ -637,25 +702,9 @@ function get_ipaddr_from_ifconfig(str){
}
}
// url related functions
function
parse_url
(){
function
parse_url
(){
let
parameters
=
location
.
href
.
replace
(
/
\?
/ig
,
"&"
).
split
(
"&"
);
let
res
=
false
;
for
(
let
i
=
0
;
i
<
parameters
.
length
;
i
++
)
parameters
[
i
]
=
parameters
[
i
].
split
(
"="
);
for
(
let
i
=
1
;
i
<
parameters
.
length
;
i
++
)
{
switch
(
parameters
[
i
][
0
])
{
case
"master"
:
update_master_node
(
parameters
[
i
][
1
]);
send_command
(
'ifconfig'
,
appData
.
slaves
,
parse_cmd_ifconfig_init
);
break
;
}
}
}
async
function
a_parse_url
(){
let
res
;
let
parameters
=
location
.
href
.
replace
(
/
\?
/ig
,
"&"
).
split
(
"&"
);
let
parameters
=
location
.
href
.
replace
(
/
\?
/ig
,
"&"
).
split
(
"&"
);
for
(
let
i
=
0
;
i
<
parameters
.
length
;
i
++
)
parameters
[
i
]
=
parameters
[
i
].
split
(
"="
);
for
(
let
i
=
0
;
i
<
parameters
.
length
;
i
++
)
parameters
[
i
]
=
parameters
[
i
].
split
(
"="
);
...
@@ -663,15 +712,14 @@ async function a_parse_url(){
...
@@ -663,15 +712,14 @@ async function a_parse_url(){
switch
(
parameters
[
i
][
0
])
{
switch
(
parameters
[
i
][
0
])
{
case
"master"
:
case
"master"
:
update_master_node
(
parameters
[
i
][
1
]);
update_master_node
(
parameters
[
i
][
1
]);
res
=
true
;
//send_command('ifconfig', appData.slaves, parse_cmd_ifconfig_init);
//send_command('ifconfig', appData.slaves, parse_cmd_ifconfig_init);
res
=
await
a_send_command
(
'ifconfig'
,
appData
.
slaves
);
//parse_cmd_ifconfig_init(res);
//parse_cmd_ifconfig_init(res);
break
;
break
;
}
}
}
}
return
res
;
return
res
;
}
}
function
rewrite_url
(){
function
rewrite_url
(){
...
@@ -696,8 +744,104 @@ function init_controls(){
...
@@ -696,8 +744,104 @@ function init_controls(){
$
(
"#rec_button"
).
on
(
"click"
,
function
(){
$
(
"#rec_button"
).
on
(
"click"
,
function
(){
States
.
recording
=
!
States
.
recording
;
States
.
recording
=
!
States
.
recording
;
rec_button_switch
(
States
.
recording
);
rec_button_switch
(
States
.
recording
);
if
(
States
.
recording
){
let
cmd
=
wget_rq
(
"camogm_interface.php?cmd=start"
);
}
else
{
let
cmd
=
wget_rq
(
"camogm_interface.php?cmd=stop"
);
}
let
targets
=
appData
.
slaves_selected
;
a_send_command
(
cmd
,
targets
).
then
(()
=>
{
console
.
log
(
"Recording: "
+
States
.
recording
);
});
});
$
(
"#snap_button"
).
on
(
"click"
,
async
function
(){
// should we stop for a moment?
let
res
=
await
a_read_params
();
// update tses
$
(
res
).
find
(
'response'
).
each
(
function
(){
const
name
=
$
(
this
).
find
(
'node'
).
text
();
let
state
=
$
(
this
).
find
(
'state'
).
text
();
const
x
=
state_str2xml
(
this
);
if
(
$
(
x
).
find
(
"camera"
).
length
==
1
)
{
const
ip
=
get_ipaddr_by_name
(
name
);
for
(
let
i
=
0
;
i
<
Cams
.
length
;
i
++
){
if
(
Cams
[
i
].
ip
===
ip
){
const
y
=
$
(
x
).
find
(
"port"
);
for
(
let
j
=
0
;
j
<
y
.
length
;
j
++
){
console
.
log
(
"Processing port "
+
$
(
y
[
j
]).
attr
(
"index"
));
Cams
[
i
].
ports
[
j
].
update_timestamps
(
$
(
y
[
j
]).
find
(
"timestamps"
));
}
break
;
}
}
}
});
// find a common ts?! or download all common?! decide by checkbox?
analyze_timestamps
();
// call for download for that ts or tses.
console
.
log
(
"Snap done"
);
});
}
function
analyze_timestamps
(){
let
newest
;
let
oldest
;
let
olds
=
[];
let
news
=
[];
for
(
let
i
=
0
;
i
<
Cams
.
length
;
i
++
){
for
(
let
j
=
0
;
j
<
Cams
[
i
].
ports
.
length
;
j
++
){
let
tmp_cam
=
Cams
[
i
];
let
tmp_port
=
tmp_cam
.
ports
[
j
];
let
tmp_tses
=
tmp_port
.
timestamps
;
olds
.
push
(
tmp_tses
[
0
].
ts
);
news
.
push
(
tmp_tses
[
tmp_tses
.
length
-
1
].
ts
);
}
}
newest
=
Math
.
min
(...
news
);
oldest
=
Math
.
max
(...
olds
);
console
.
log
(
"Timestamp range: "
+
oldest
+
" - "
+
newest
);
// let get the newest for now
// need pointers
let
ptrs
=
[];
for
(
let
i
=
0
;
i
<
Cams
.
length
;
i
++
){
for
(
let
j
=
0
;
j
<
Cams
[
i
].
ports
.
length
;
j
++
){
let
tmp_cam
=
Cams
[
i
];
let
tmp_port
=
tmp_cam
.
ports
[
j
];
let
tmp_tses
=
tmp_port
.
timestamps
;
ptrs
.
push
({
cam
:
i
,
port
:
j
,
ptr
:
tmp_tses
.
filter
(
a
=>
a
.
ts
===
newest
)[
0
].
ptr
});
});
}
}
return
ptrs
;
}
}
function
rec_button_switch
(
state
){
function
rec_button_switch
(
state
){
...
@@ -722,6 +866,15 @@ function init_awb_toggle(){
...
@@ -722,6 +866,15 @@ function init_awb_toggle(){
wb_en
=
1
;
wb_en
=
1
;
}
}
let
cmd
=
wget_rq
(
"parsedit.php?immediate&sensor_port=0&WB_EN="
+
wb_en
+
"&*WB_EN=0xf"
);
let
targets
=
appData
.
slaves_selected
;
console
.
log
(
"Hoping to set Auto White Balance to "
+
wb_en
);
a_send_command
(
cmd
,
targets
).
then
(()
=>
{
console
.
log
(
"Auto White Balance: "
+
wb_en
);
});
button_switch
(
$
(
this
),
wb_en
);
button_switch
(
$
(
this
),
wb_en
);
// will it work without port 0?
// will it work without port 0?
...
@@ -783,8 +936,18 @@ function button_switch(btn,state){
...
@@ -783,8 +936,18 @@ function button_switch(btn,state){
}
}
// helper functions
function
get_ipaddr_by_name
(
name
){
for
(
let
i
=
0
;
i
<
appData
.
slaves
.
length
;
i
++
){
if
(
name
==
appData
.
slaves
[
i
]){
return
appData
.
ips
[
i
];
}
}
return
""
;
}
// helper functions
function
fps_period2fps
(
period
){
function
fps_period2fps
(
period
){
// the tick is 10ns, so:
// the tick is 10ns, so:
...
@@ -792,13 +955,19 @@ function fps_period2fps(period){
...
@@ -792,13 +955,19 @@ function fps_period2fps(period){
}
}
function
fps_fps2period
(
fps
){
return
(
1
e8
/
fps
).
toFixed
();
}
function
format_str2num
(
str
){
function
format_str2num
(
str
){
let
num
;
let
num
;
switch
(
str
){
switch
(
str
.
toLowerCase
()
){
case
"jp4"
:
num
=
5
;
break
;
case
"jp4"
:
num
=
5
;
break
;
case
"jpeg"
:
num
=
0
;
break
;
case
"jpeg"
:
num
=
0
;
break
;
default
:
num
=
-
1
;
default
:
num
=
0
;
}
}
return
num
;
return
num
;
...
...
public/javascripts/snapshot.js
0 → 100644
View file @
cfcf6b51
var
zip_filename
=
"zip.zip"
;
var
filenames
=
[];
var
blobs
=
[];
var
snapshot_counter
=
0
;
var
zip_counter
=
0
;
var
blob_counter
=
0
;
function
snapshot_download_all
(
ptrs
){
var
ts
=
snapshot_find_latest_ts
(
ptrs
);
if
(
ts
){
zip_filename
=
ts
.
replace
(
/
\.
/ig
,
"_"
)
+
".zip"
;
snapshot_counter
=
0
;
zip_counter
=
0
;
blob_counter
=
0
;
filenames
=
[];
blobs
=
[];
for
(
var
i
=
0
;
i
<
ptrs
.
length
;
i
++
){
var
ip
=
$
(
ptrs
[
i
]).
find
(
'camera'
).
attr
(
'ip'
);
var
bchn
=
get_base_channel
(
ip
);
//console.log(ip+": base channel = "+base_chn);
var
buf_pointers
=
$
(
ptrs
[
i
]).
find
(
'ts[ts=
\'
'
+
ts
+
'
\'
]'
);
for
(
var
j
=
0
;
j
<
cams
[
i
].
ports
.
length
;
j
++
){
// everything is ordered
var
port
=
cams
[
i
].
ports
[
j
].
port
;
var
pointer
=
$
(
buf_pointers
[
j
]).
attr
(
'ptr'
);
var
url
=
"http://"
+
ip
+
":"
+
port
+
"/"
+
pointer
+
"/timestamp_name/bchn"
+
bchn
+
"/bimg"
;
snapshot_download_single
(
url
);
}
}
}
}
// from snapshot.js
function
snapshot_download_single
(
addr
){
snapshot_counter
++
;
// get ze blob
var
http
=
new
XMLHttpRequest
();
http
.
open
(
"GET"
,
addr
,
true
);
http
.
responseType
=
"blob"
;
http
.
onload
=
function
(
e
){
if
(
this
.
status
===
200
)
{
// To access the header, had to add
// printf("Access-Control-Expose-Headers: Content-Disposition\r\n");
// to imgsrv
var
filename
=
this
.
getResponseHeader
(
"Content-Disposition"
);
filename
=
filename_from_content_disposition
(
filename
);
// store in case zip cannot zip
filenames
.
push
(
filename
);
blobs
.
push
(
http
.
response
);
blob_counter
++
;
if
(
blob_counter
==
snapshot_counter
){
zip_blobs
();
}
}
}
http
.
send
();
}
function
zip_blobs
(){
zip
.
createWriter
(
new
zip
.
BlobWriter
(
"application/zip"
),
function
(
writer
)
{
var
f
=
0
;
function
nextFile
(
f
)
{
fblob
=
blobs
[
f
];
writer
.
add
(
filenames
[
f
],
new
zip
.
BlobReader
(
fblob
),
function
()
{
// callback
f
++
;
if
(
f
<
filenames
.
length
)
{
nextFile
(
f
);
}
else
close
();
});
}
function
close
()
{
// close the writer
writer
.
close
(
function
(
blob
)
{
// save with FileSaver.js
pass_to_file_reader
(
zip_filename
,
blob
);
});
}
nextFile
(
f
);
},
onerror
);
}
function
filename_from_content_disposition
(
str
){
var
parameters
=
str
.
split
(
";"
);
for
(
var
i
=
0
;
i
<
parameters
.
length
;
i
++
)
parameters
[
i
]
=
parameters
[
i
].
split
(
"="
);
for
(
var
i
=
0
;
i
<
parameters
.
length
;
i
++
)
{
if
(
parameters
[
i
][
0
].
trim
()
==
"filename"
){
str
=
parameters
[
i
][
1
].
replace
(
/"/ig
,
""
);
str
=
str
.
trim
();
}
}
return
str
;
}
// from here:
// https://diegolamonica.info/multiple-files-download-on-single-link-click/
// http://jsfiddle.net/diegolamonica/ssk8z9pa/
// (helped a lot) https://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link
function
pass_to_file_reader
(
filename
,
fileblob
){
var
url
=
window
.
URL
.
createObjectURL
(
fileblob
);
var
a
=
$
(
'<a>'
)
.
attr
(
'href'
,
url
)
.
attr
(
'download'
,
filename
)
// Firefox does not fire click if the link is outside
// the DOM
.
appendTo
(
'body'
);
a
[
0
].
click
();
//a.click();
// delay?
setTimeout
(
function
(){
a
.
remove
();
},
200
);
}
public/stylesheets/style.css
View file @
cfcf6b51
...
@@ -121,7 +121,11 @@ input[type="checkbox"], input[type="radio"] {
...
@@ -121,7 +121,11 @@ input[type="checkbox"], input[type="radio"] {
width
:
80%
;
width
:
80%
;
height
:
80%
;
height
:
80%
;
border-radius
:
50%
;
border-radius
:
50%
;
background
:
rgba
(
150
,
150
,
150
,
1
);
background
:
rgba
(
210
,
210
,
210
,
1
);
}
.snap_inner
:hover
{
background
:
rgb
(
150
,
150
,
150
,
1
);
}
}
.snap_inner
:active
{
.snap_inner
:active
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment