reinventing alert/confirm/prompt was exactly what i had in mind for the weekend, thanks google

This commit is contained in:
ed 2021-08-07 18:41:06 +02:00
parent 4fcfd87f5b
commit d52038366b
14 changed files with 785 additions and 666 deletions

View file

@ -25,122 +25,6 @@ html, body {
pre, code, tt { pre, code, tt {
font-family: monospace, monospace; font-family: monospace, monospace;
} }
#tt, #toast {
position: fixed;
max-width: 34em;
background: #222;
border: 0 solid #777;
box-shadow: 0 .2em .5em #222;
border-radius: .4em;
z-index: 9001;
}
#tt {
overflow: hidden;
margin-top: 1em;
padding: 0 1.3em;
height: 0;
opacity: .1;
transition: opacity 0.14s, height 0.14s, padding 0.14s;
}
#toast {
bottom: 5em;
right: -1em;
line-height: 1.5em;
padding: 1em 1.3em;
border-width: .4em 0;
transform: translateX(100%);
transition:
transform .4s cubic-bezier(.2, 1.2, .5, 1),
right .4s cubic-bezier(.2, 1.2, .5, 1);
text-shadow: 1px 1px 0 #000;
color: #fff;
}
#toastc {
display: inline-block;
position: absolute;
overflow: hidden;
left: 0;
width: 0;
opacity: 0;
padding: .3em 0;
margin: -.3em 0 0 0;
line-height: 1.5em;
color: #000;
border: none;
outline: none;
text-shadow: none;
border-radius: .5em 0 0 .5em;
transition: left .3s, width .3s, padding .3s, opacity .3s;
}
#toast pre {
margin: 0;
}
#toast.vis {
right: 1.3em;
transform: unset;
}
#toast.vis #toastc {
left: -2em;
width: .4em;
padding: .3em .8em;
opacity: 1;
}
#toast.inf {
background: #07a;
border-color: #0be;
}
#toast.inf #toastc {
background: #0be;
}
#toast.ok {
background: #4a0;
border-color: #8e4;
}
#toast.ok #toastc {
background: #8e4;
}
#toast.warn {
background: #970;
border-color: #fc0;
}
#toast.warn #toastc {
background: #fc0;
}
#toast.err {
background: #900;
border-color: #d06;
}
#toast.err #toastc {
background: #d06;
}
#tt.b {
padding: 0 2em;
border-radius: .5em;
box-shadow: 0 .2em 1em #000;
}
#tt.show {
padding: 1em 1.3em;
border-width: .4em 0;
height: auto;
opacity: 1;
}
#tt.show.b {
padding: 1.5em 2em;
border-width: .5em 0;
}
#tt code {
background: #3c3c3c;
padding: .1em .3em;
border-top: 1px solid #777;
border-radius: .3em;
line-height: 1.7em;
}
#tt em {
color: #f6a;
}
#path, #path,
#path * { #path * {
font-size: 1em; font-size: 1em;
@ -1075,6 +959,7 @@ html.light #ggrid a:hover {
overflow: auto; overflow: auto;
max-height: calc(100% - 2em); max-height: calc(100% - 2em);
border-bottom: .5em solid #999; border-bottom: .5em solid #999;
box-shadow: 0 0 5em rgba(0,0,0,0.8);
background: #333; background: #333;
padding: 1em; padding: 1em;
z-index: 765; z-index: 765;
@ -1149,6 +1034,11 @@ html.light #rui {
@ -1159,21 +1049,6 @@ html.light {
background: #eee; background: #eee;
text-shadow: none; text-shadow: none;
} }
html.light #tt {
background: #fff;
border-color: #888 #000 #777 #000;
}
html.light #tt,
html.light #toast {
box-shadow: 0 .3em 1em rgba(0,0,0,0.4);
}
html.light #tt code {
background: #060;
color: #fff;
}
html.light #tt em {
color: #d38;
}
html.light #ops, html.light #ops,
html.light .opbox, html.light .opbox,
html.light #srch_form { html.light #srch_form {
@ -1390,6 +1265,30 @@ html.light #tree::-webkit-scrollbar {
/* bbox */
#bbox-overlay { #bbox-overlay {
display: none; display: none;
opacity: 0; opacity: 0;
@ -1568,3 +1467,331 @@ html.light #bbox-overlay figcaption a {
0%, 100% {transform: scale(0)} 0%, 100% {transform: scale(0)}
50% {transform: scale(1)} 50% {transform: scale(1)}
} }
/* upload.css */
#op_up2k {
padding: 0 1em 1em 1em;
}
#u2form {
position: absolute;
top: 0;
left: 0;
width: 2px;
height: 2px;
overflow: hidden;
}
#u2form input {
background: #444;
border: 0px solid #444;
outline: none;
}
#u2err.err {
color: #f87;
padding: .5em;
}
#u2err.msg {
color: #999;
padding: .5em;
font-size: .9em;
}
#u2btn {
color: #eee;
background: #555;
background: -moz-linear-gradient(top, #367 0%, #489 50%, #38788a 51%, #367 100%);
background: -webkit-linear-gradient(top, #367 0%, #489 50%, #38788a 51%, #367 100%);
background: linear-gradient(to bottom, #367 0%, #489 50%, #38788a 51%, #367 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#489', endColorstr='#38788a', GradientType=0);
text-decoration: none;
line-height: 1.3em;
border: 1px solid #222;
border-radius: .4em;
text-align: center;
font-size: 1.5em;
margin: .5em auto;
padding: .8em 0;
width: 16em;
cursor: pointer;
box-shadow: .4em .4em 0 #111;
}
#op_up2k.srch #u2btn {
background: linear-gradient(to bottom, #ca3 0%, #fd8 50%, #fc6 51%, #b92 100%);
text-shadow: 1px 1px 1px #fc6;
color: #333;
}
#u2conf #u2btn {
margin: -1.5em 0;
padding: .8em 0;
width: 100%;
max-width: 12em;
display: inline-block;
}
#u2conf #u2btn_cw {
text-align: right;
}
#u2notbtn {
display: none;
text-align: center;
background: #333;
padding-top: 1em;
}
#u2notbtn * {
line-height: 1.3em;
}
#u2tab {
margin: 3em auto;
width: calc(100% - 2em);
max-width: 100em;
}
#op_up2k.srch #u2tab {
max-width: none;
}
#u2tab td {
border: 1px solid #ccc;
border-width: 0 0px 1px 0;
padding: .1em .3em;
}
#u2tab td:nth-child(2) {
width: 5em;
white-space: nowrap;
}
#u2tab td:nth-child(3) {
width: 40%;
}
#op_up2k.srch td.prog {
font-family: sans-serif;
font-size: 1em;
width: auto;
}
#u2tab tbody tr:hover td {
background: #222;
}
#u2cards {
padding: 1em 0 .3em 1em;
margin: 1.5em auto -2.5em auto;
white-space: nowrap;
text-align: center;
overflow: hidden;
}
#u2cards.w {
width: 45em;
text-align: left;
}
#u2cards a {
padding: .2em 1em;
border: 1px solid #777;
border-width: 0 0 1px 0;
background: linear-gradient(to bottom, #333, #222);
}
#u2cards a:first-child {
border-radius: .4em 0 0 0;
}
#u2cards a:last-child {
border-radius: 0 .4em 0 0;
}
#u2cards a.act {
padding-bottom: .5em;
border-width: 1px 1px .1em 1px;
border-radius: .3em .3em 0 0;
margin-left: -1px;
background: linear-gradient(to bottom, #464, #333 80%);
box-shadow: 0 -.17em .67em #280;
border-color: #7c5 #583 #333 #583;
position: relative;
color: #fd7;
}
#u2cards span {
color: #fff;
}
#u2conf {
margin: 1em auto;
width: 30em;
}
#u2conf.has_btn {
width: 48em;
}
#u2conf * {
text-align: center;
line-height: 1em;
margin: 0;
padding: 0;
border: none;
outline: none;
}
#u2conf .txtbox {
width: 3em;
color: #fff;
background: #444;
border: 1px solid #777;
font-size: 1.2em;
padding: .15em 0;
height: 1.05em;
}
#u2conf .txtbox.err {
background: #922;
}
#u2conf a {
color: #fff;
background: #c38;
text-decoration: none;
border-radius: .1em;
font-size: 1.5em;
padding: .1em 0;
margin: 0 -1px;
width: 1.5em;
height: 1em;
display: inline-block;
position: relative;
bottom: -0.08em;
}
#u2conf input+a {
background: #d80;
}
#u2conf label {
font-size: 1.6em;
width: 2em;
height: 1em;
padding: .4em 0;
display: block;
border-radius: .25em;
}
#u2conf input[type="checkbox"] {
position: relative;
opacity: .02;
top: 2em;
}
#u2conf input[type="checkbox"]+label {
position: relative;
background: #603;
border-bottom: .2em solid #a16;
box-shadow: 0 .1em .3em #a00 inset;
}
#u2conf input[type="checkbox"]:checked+label {
background: #6a1;
border-bottom: .2em solid #efa;
box-shadow: 0 .1em .5em #0c0;
}
#u2conf input[type="checkbox"]+label:hover {
box-shadow: 0 .1em .3em #fb0;
border-color: #fb0;
}
#op_up2k.srch #u2conf td:nth-child(1)>*,
#op_up2k.srch #u2conf td:nth-child(2)>*,
#op_up2k.srch #u2conf td:nth-child(3)>* {
background: #777;
border-color: #ccc;
box-shadow: none;
opacity: .2;
}
#u2foot {
color: #fff;
font-style: italic;
}
#u2foot .warn {
font-size: 1.3em;
padding: .5em .8em;
margin: 1em -.6em;
color: #f74;
background: #322;
border: 1px solid #633;
border-width: .1em 0;
text-align: center;
}
#u2foot .warn span {
color: #f86;
}
html.light #u2foot .warn {
color: #b00;
background: #fca;
border-color: #f70;
}
html.light #u2foot .warn span {
color: #930;
}
#u2foot span {
color: #999;
font-size: .9em;
font-weight: normal;
}
#u2footfoot {
margin-bottom: -1em;
}
.prog {
font-family: monospace, monospace;
}
#u2tab a>span {
font-weight: bold;
font-style: italic;
color: #fff;
padding-left: .2em;
}
#u2cleanup {
float: right;
margin-bottom: -.3em;
}
.fsearch_explain {
padding-left: .7em;
font-size: 1.1em;
line-height: 0;
}
html.light #u2btn {
box-shadow: .4em .4em 0 #ccc;
}
html.light #u2cards span {
color: #000;
}
html.light #u2cards a {
background: linear-gradient(to bottom, #eee, #fff);
}
html.light #u2cards a.act {
color: #037;
background: inherit;
box-shadow: 0 -.17em .67em #0ad;
border-color: #09c #05a #eee #05a;
}
html.light #u2conf .txtbox {
background: #fff;
color: #444;
}
html.light #u2conf .txtbox.err {
background: #f96;
color: #300;
}
html.light #op_up2k.srch #u2btn {
border-color: #a80;
}
html.light #u2foot {
color: #000;
}
html.light #u2tab tbody tr:hover td {
background: #fff;
}

View file

@ -6,10 +6,10 @@
<title>⇆🎉 {{ title }}</title> <title>⇆🎉 {{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8"> <meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/browser.css?_={{ ts }}"> <link rel="stylesheet" media="screen" href="/.cpr/ui.css?_={{ ts }}">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/upload.css?_={{ ts }}"> <link rel="stylesheet" media="screen" href="/.cpr/browser.css?_={{ ts }}">
{%- if css %} {%- if css %}
<link rel="stylesheet" type="text/css" media="screen" href="{{ css }}?_={{ ts }}"> <link rel="stylesheet" media="screen" href="{{ css }}?_={{ ts }}">
{%- endif %} {%- endif %}
</head> </head>

View file

@ -1283,11 +1283,12 @@ function play(tid, is_ev, seek, call_depth) {
} }
else { else {
if (call_depth !== undefined) if (call_depth !== undefined)
return alert('failed to load ogv.js'); return toast.err(0, 'failed to load ogv.js:\ncannot play ogg/opus in this browser');
show_modal('<h1>loading ogv.js</h1><h2>thanks apple</h2>'); toast.inf(0, '<h1>loading ogv.js</h1><h2>thanks apple</h2>');
import_js('/.cpr/deps/ogv.js', function () { import_js('/.cpr/deps/ogv.js', function () {
toast.hide();
play(tid, false, seek, 1); play(tid, false, seek, 1);
}); });
@ -1383,7 +1384,7 @@ function evau_error(e) {
err += '\n\nFile: «' + uricom_dec(eplaya.src.split('/').slice(-1)[0])[0] + '»'; err += '\n\nFile: «' + uricom_dec(eplaya.src.split('/').slice(-1)[0])[0] + '»';
alert(err); toast.warn(15, err);
} }
@ -1776,7 +1777,7 @@ var fileman = (function () {
} }
} }
inew.onclick = function () { inew.onclick = function () {
var name = prompt('provide a name for your new preset', ifmt.value); modal.prompt('provide a name for your new preset', ifmt.value, function (name) {
if (!name) if (!name)
return toast.warn(3, 'aborted'); return toast.warn(3, 'aborted');
@ -1784,6 +1785,7 @@ var fileman = (function () {
jwrite('rn_pre', presets); jwrite('rn_pre', presets);
spresets(); spresets();
ipre.value = name; ipre.value = name;
});
}; };
idel.onclick = function () { idel.onclick = function () {
delete presets[ipre.value]; delete presets[ipre.value];
@ -1891,12 +1893,6 @@ var fileman = (function () {
if (!sel.length) if (!sel.length)
return toast.err(3, 'select at least 1 item to delete'); return toast.err(3, 'select at least 1 item to delete');
if (!confirm('===== DANGER =====\nDELETE these ' + vps.length + ' items?\n\n' + vps.join('\n')))
return;
if (!confirm('Last chance! Delete?'))
return;
function deleter() { function deleter() {
var xhr = new XMLHttpRequest(), var xhr = new XMLHttpRequest(),
vp = vps.shift(); vp = vps.shift();
@ -1923,7 +1919,10 @@ var fileman = (function () {
} }
deleter(); deleter();
} }
deleter();
modal.confirm('===== DANGER =====\nDELETE these ' + vps.length + ' items?\n\n' + vps.join('\n'), function () {
modal.confirm('Last chance! Delete?', deleter, null);
}, null);
}; };
r.cut = function (e) { r.cut = function (e) {
@ -1981,14 +1980,11 @@ var fileman = (function () {
} }
if (exists.length) if (exists.length)
alert('these ' + exists.length + ' items cannot be pasted here (names already exist):\n\n' + uricom_adec(exists).join('\n')); toast.warn(30, 'these ' + exists.length + ' items cannot be pasted here (names already exist):\n\n' + uricom_adec(exists).join('\n'));
if (!req.length) if (!req.length)
return; return;
if (!confirm('paste these ' + req.length + ' items here?\n\n' + uricom_adec(req).join('\n')))
return;
function paster() { function paster() {
var xhr = new XMLHttpRequest(), var xhr = new XMLHttpRequest(),
vp = req.shift(); vp = req.shift();
@ -2018,9 +2014,11 @@ var fileman = (function () {
} }
paster(); paster();
} }
paster();
modal.confirm('paste these ' + req.length + ' items here?\n\n' + uricom_adec(req).join('\n'), function () {
paster();
jwrite('fman_clip', []); jwrite('fman_clip', []);
}, null);
}; };
r.bus.onmessage = function (e) { r.bus.onmessage = function (e) {

View file

@ -8,140 +8,6 @@ html, body {
font-family: sans-serif; font-family: sans-serif;
line-height: 1.5em; line-height: 1.5em;
} }
#tt, #toast {
position: fixed;
max-width: 34em;
background: #222;
border: 0 solid #777;
box-shadow: 0 .2em .5em #222;
border-radius: .4em;
z-index: 9001;
}
#tt {
overflow: hidden;
margin-top: 1em;
padding: 0 1.3em;
height: 0;
opacity: .1;
transition: opacity 0.14s, height 0.14s, padding 0.14s;
}
#toast {
top: 1.4em;
right: -1em;
line-height: 1.5em;
padding: 1em 1.3em;
border-width: .4em 0;
transform: translateX(100%);
transition:
transform .4s cubic-bezier(.2, 1.2, .5, 1),
right .4s cubic-bezier(.2, 1.2, .5, 1);
text-shadow: 1px 1px 0 #000;
color: #fff;
}
#toast pre {
margin: 0;
}
#toastc {
display: inline-block;
position: absolute;
overflow: hidden;
left: 0;
width: 0;
opacity: 0;
padding: .3em 0;
margin: -.3em 0 0 0;
line-height: 1.5em;
color: #000;
border: none;
outline: none;
text-shadow: none;
border-radius: .5em 0 0 .5em;
transition: left .3s, width .3s, padding .3s, opacity .3s;
}
#toast.vis {
right: 1.3em;
transform: unset;
}
#toast.vis #toastc {
left: -2em;
width: .4em;
padding: .3em .8em;
opacity: 1;
}
#toast.inf {
background: #07a;
border-color: #0be;
}
#toast.inf #toastc {
background: #0be;
}
#toast.ok {
background: #4a0;
border-color: #8e4;
}
#toast.ok #toastc {
background: #8e4;
}
#toast.warn {
background: #970;
border-color: #fc0;
}
#toast.warn #toastc {
background: #fc0;
}
#toast.err {
background: #900;
border-color: #d06;
}
#toast.err #toastc {
background: #d06;
}
#tt.b {
padding: 0 2em;
border-radius: .5em;
box-shadow: 0 .2em 1em #000;
}
#tt.show {
padding: 1em 1.3em;
border-width: .4em 0;
height: auto;
opacity: 1;
}
#tt.show.b {
padding: 1.5em 2em;
border-width: .5em 0;
}
#tt code {
background: #3c3c3c;
padding: .1em .3em;
border-top: 1px solid #777;
border-radius: .3em;
line-height: 1.7em;
}
#tt em {
color: #f6a;
}
html.light #tt {
background: #fff;
border-color: #888 #000 #777 #000;
}
html.light #tt,
html.light #toast {
box-shadow: 0 .3em 1em rgba(0,0,0,0.4);
}
html.light #tt code {
background: #060;
color: #fff;
}
html.light #tt em {
color: #d38;
}
#mtw { #mtw {
display: none; display: none;
} }
@ -149,6 +15,10 @@ html.light #tt em {
margin: 0 auto; margin: 0 auto;
padding: 0 1.5em; padding: 0 1.5em;
} }
#toast {
bottom: auto;
top: 1.4em;
}
pre, code, a { pre, code, a {
color: #480; color: #480;
background: #f7f7f7; background: #f7f7f7;

View file

@ -1,11 +1,12 @@
<!DOCTYPE html><html><head> <!DOCTYPE html><html><head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>📝🎉 {{ title }}</title> <!-- 📜 --> <title>📝🎉 {{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.7"> <meta name="viewport" content="width=device-width, initial-scale=0.7">
<link href="/.cpr/md.css?_={{ ts }}" rel="stylesheet"> <link rel="stylesheet" href="/.cpr/ui.css?_={{ ts }}">
<link rel="stylesheet" href="/.cpr/md.css?_={{ ts }}">
{%- if edit %} {%- if edit %}
<link href="/.cpr/md2.css?_={{ ts }}" rel="stylesheet"> <link rel="stylesheet" href="/.cpr/md2.css?_={{ ts }}">
{%- endif %} {%- endif %}
</head> </head>
<body> <body>

View file

@ -185,7 +185,7 @@ function md_plug_err(ex, js) {
errbox.style.cssText = 'position:absolute;top:0;left:0;padding:1em .5em;background:#2b2b2b;color:#fc5' errbox.style.cssText = 'position:absolute;top:0;left:0;padding:1em .5em;background:#2b2b2b;color:#fc5'
errbox.textContent = msg; errbox.textContent = msg;
errbox.onclick = function () { errbox.onclick = function () {
alert('' + ex.stack); modal.alert('<pre>' + ex.stack + '</pre>');
}; };
if (o) { if (o) {
errbox.appendChild(o); errbox.appendChild(o);

View file

@ -326,12 +326,10 @@ function save(e) {
return toast.inf(2, "no changes"); return toast.inf(2, "no changes");
var force = (save_cls.indexOf('force-save') >= 0); var force = (save_cls.indexOf('force-save') >= 0);
if (force && !confirm('confirm that you wish to lose the changes made on the server since you opened this document')) function save2() {
return toast.inf(3, 'aborted'); var txt = dom_src.value,
fd = new FormData();
var txt = dom_src.value;
var fd = new FormData();
fd.append("act", "tput"); fd.append("act", "tput");
fd.append("lastmod", (force ? -1 : last_modified)); fd.append("lastmod", (force ? -1 : last_modified));
fd.append("body", txt); fd.append("body", txt);
@ -346,6 +344,14 @@ function save(e) {
modpoll.skip_one = true; // skip one iteration while we save modpoll.skip_one = true; // skip one iteration while we save
xhr.send(fd); xhr.send(fd);
}
if (!force)
save2();
else
modal.confirm('confirm that you wish to lose the changes made on the server since you opened this document', save2, function () {
toast.inf(3, 'aborted');
});
} }
function save_cb() { function save_cb() {
@ -353,14 +359,14 @@ function save_cb() {
return; return;
if (this.status !== 200) if (this.status !== 200)
return alert('Error! The file was NOT saved.\n\n' + this.status + ": " + (this.responseText + '').replace(/^<pre>/, "")); return toast.err(0, 'Error! The file was NOT saved.\n\n' + this.status + ": " + (this.responseText + '').replace(/^<pre>/, ""));
var r; var r;
try { try {
r = JSON.parse(this.responseText); r = JSON.parse(this.responseText);
} }
catch (ex) { catch (ex) {
return alert('Failed to parse reply from server:\n\n' + this.responseText); return toast.err(0, 'Failed to parse reply from server:\n\n' + this.responseText);
} }
if (!r.ok) { if (!r.ok) {
@ -375,12 +381,10 @@ function save_cb() {
r.lastmod + ' lastmod on the server now,', r.lastmod + ' lastmod on the server now,',
r.now + ' server time now,\n', r.now + ' server time now,\n',
]; ];
alert(msg.join('\n')); return toast.err(0, msg.join('\n'));
} }
else { else
alert('Error! Save failed. Maybe this JSON explains why:\n\n' + this.responseText); return toast.err(0, 'Error! Save failed. Maybe this JSON explains why:\n\n' + this.responseText);
}
return;
} }
this.btn.classList.remove('force-save'); this.btn.classList.remove('force-save');
@ -407,10 +411,8 @@ function savechk_cb() {
if (this.readyState != XMLHttpRequest.DONE) if (this.readyState != XMLHttpRequest.DONE)
return; return;
if (this.status !== 200) { if (this.status !== 200)
alert('Error! The file was NOT saved.\n\n' + this.status + ": " + (this.responseText + '').replace(/^<pre>/, "")); return toast.err(0, 'Error! The file was NOT saved.\n\n' + this.status + ": " + (this.responseText + '').replace(/^<pre>/, ""));
return;
}
var doc1 = this.txt.replace(/\r\n/g, "\n"); var doc1 = this.txt.replace(/\r\n/g, "\n");
var doc2 = this.responseText.replace(/\r\n/g, "\n"); var doc2 = this.responseText.replace(/\r\n/g, "\n");
@ -423,12 +425,12 @@ function savechk_cb() {
}, 100); }, 100);
return; return;
} }
alert( modal.alert(
'Error! The document on the server does not appear to have saved correctly (your editor contents and the server copy is not identical). Place the document on your clipboard for now and check the server logs for hints\n\n' + 'Error! The document on the server does not appear to have saved correctly (your editor contents and the server copy is not identical). Place the document on your clipboard for now and check the server logs for hints\n\n' +
'Length: yours=' + doc1.length + ', server=' + doc2.length 'Length: yours=' + doc1.length + ', server=' + doc2.length
); );
alert('yours, ' + doc1.length + ' byte:\n[' + doc1 + ']'); modal.alert('yours, ' + doc1.length + ' byte:\n[' + doc1 + ']');
alert('server, ' + doc2.length + ' byte:\n[' + doc2 + ']'); modal.alert('server, ' + doc2.length + ' byte:\n[' + doc2 + ']');
return; return;
} }
@ -865,12 +867,10 @@ function iter_uni(e) {
function cfg_uni(e) { function cfg_uni(e) {
if (e) e.preventDefault(); if (e) e.preventDefault();
var reply = prompt("unicode whitelist", esc_uni_whitelist); modal.prompt("unicode whitelist", esc_uni_whitelist, function (reply) {
if (reply === null)
return;
esc_uni_whitelist = reply; esc_uni_whitelist = reply;
js_uni_whitelist = eval('\'' + esc_uni_whitelist + '\''); js_uni_whitelist = eval('\'' + esc_uni_whitelist + '\'');
}, null);
} }

View file

@ -3,9 +3,9 @@
<title>📝🎉 {{ title }}</title> <title>📝🎉 {{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.7"> <meta name="viewport" content="width=device-width, initial-scale=0.7">
<link href="/.cpr/mde.css?_={{ ts }}" rel="stylesheet"> <link rel="stylesheet" href="/.cpr/mde.css?_={{ ts }}">
<link href="/.cpr/deps/mini-fa.css?_={{ ts }}" rel="stylesheet"> <link rel="stylesheet" href="/.cpr/deps/mini-fa.css?_={{ ts }}">
<link href="/.cpr/deps/easymde.css?_={{ ts }}" rel="stylesheet"> <link rel="stylesheet" href="/.cpr/deps/easymde.css?_={{ ts }}">
</head> </head>
<body> <body>
<div id="mw"> <div id="mw">

View file

@ -6,7 +6,7 @@
<title>copyparty</title> <title>copyparty</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8"> <meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/msg.css?_={{ ts }}"> <link rel="stylesheet" media="screen" href="/.cpr/msg.css?_={{ ts }}">
</head> </head>
<body> <body>

View file

@ -6,7 +6,7 @@
<title>copyparty</title> <title>copyparty</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8"> <meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/splash.css?_={{ ts }}"> <link rel="stylesheet" media="screen" href="/.cpr/splash.css?_={{ ts }}">
</head> </head>
<body> <body>

196
copyparty/web/ui.css Normal file
View file

@ -0,0 +1,196 @@
#tt, #toast {
position: fixed;
max-width: 34em;
background: #222;
border: 0 solid #777;
box-shadow: 0 .2em .5em #222;
border-radius: .4em;
z-index: 9001;
}
#tt {
overflow: hidden;
margin-top: 1em;
padding: 0 1.3em;
height: 0;
opacity: .1;
transition: opacity 0.14s, height 0.14s, padding 0.14s;
}
#toast {
bottom: 5em;
right: -1em;
line-height: 1.5em;
padding: 1em 1.3em;
border-width: .4em 0;
transform: translateX(100%);
transition:
transform .4s cubic-bezier(.2, 1.2, .5, 1),
right .4s cubic-bezier(.2, 1.2, .5, 1);
text-shadow: 1px 1px 0 #000;
color: #fff;
}
#toastc {
display: inline-block;
position: absolute;
overflow: hidden;
left: 0;
width: 0;
opacity: 0;
padding: .3em 0;
margin: -.3em 0 0 0;
line-height: 1.5em;
color: #000;
border: none;
outline: none;
text-shadow: none;
border-radius: .5em 0 0 .5em;
transition: left .3s, width .3s, padding .3s, opacity .3s;
}
#toast pre {
margin: 0;
}
#toast.vis {
right: 1.3em;
transform: unset;
}
#toast.vis #toastc {
left: -2em;
width: .4em;
padding: .3em .8em;
opacity: 1;
}
#toast.inf {
background: #07a;
border-color: #0be;
}
#toast.inf #toastc {
background: #0be;
}
#toast.ok {
background: #4a0;
border-color: #8e4;
}
#toast.ok #toastc {
background: #8e4;
}
#toast.warn {
background: #970;
border-color: #fc0;
}
#toast.warn #toastc {
background: #fc0;
}
#toast.err {
background: #900;
border-color: #d06;
}
#toast.err #toastc {
background: #d06;
}
#tt.b {
padding: 0 2em;
border-radius: .5em;
box-shadow: 0 .2em 1em #000;
}
#tt.show {
padding: 1em 1.3em;
border-width: .4em 0;
height: auto;
opacity: 1;
}
#tt.show.b {
padding: 1.5em 2em;
border-width: .5em 0;
}
#tt code {
background: #3c3c3c;
padding: .1em .3em;
border-top: 1px solid #777;
border-radius: .3em;
line-height: 1.7em;
}
#tt em {
color: #f6a;
}
html.light #tt {
background: #fff;
border-color: #888 #000 #777 #000;
}
html.light #tt,
html.light #toast {
box-shadow: 0 .3em 1em rgba(0,0,0,0.4);
}
html.light #tt code {
background: #060;
color: #fff;
}
html.light #tt em {
color: #d38;
}
#modal {
position: fixed;
overflow: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 9001;
background: rgba(64,64,64,0.6);
}
#modal>table {
width: 100%;
height: 100%;
}
#modal td {
text-align: center;
}
#modalc {
display: inline-block;
background: #f7f7f7;
color: #333;
text-shadow: none;
text-align: left;
margin: 3em;
padding: 1em 1.1em;
border-radius: .6em;
box-shadow: 0 .3em 3em rgba(0,0,0,0.5);
}
@media (min-width: 40em) {
#modalc {
min-width: 30em;
}
}
#modalb {
text-align: right;
padding-top: 1em;
}
#modalb a {
color: #000;
background: #ccc;
display: inline-block;
border-radius: .3em;
padding: .5em 1em;
outline: none;
border: none;
}
#modalb a:focus,
#modalb a:hover {
background: #06d;
color: #fff;
}
#modalb a+a {
margin-left: .5em;
}
#modali {
display: block;
width: calc(100% - 1.25em);
margin: 1em -.1em 0 -.1em;
padding: .5em;
outline: none;
border: .25em solid #ccc;
border-radius: .4em;
}
#modali:focus {
border-color: #06d;
}

View file

@ -460,12 +460,14 @@ function U2pvis(act, btns) {
} }
function fsearch_explain(e) { function fsearch_explain(n) {
ev(e); if (n)
if (!has(perms, 'write')) return toast.inf(60, 'your access to this folder is Read-Only\n\n' + (acct == '*' ? 'you are currently not logged in' : 'you are currently logged in as "' + acct + '"'));
return alert('your access to this folder is Read-Only\n\n' + (acct == '*' ? 'you are currently not logged in' : 'you are currently logged in as ' + acct));
alert('you are currently in file-search mode\n\nswitch to upload-mode by clicking the green magnifying glass (next to the big yellow search button), and then refresh\n\nsorry'); if (bcfg_get('fsearch', false))
return toast.inf(60, 'you are currently in file-search mode\n\nswitch to upload-mode by clicking the green magnifying glass (next to the big yellow search button), and then refresh\n\nsorry');
return toast.inf(60, 'refresh the page and try again, it should work now');
} }
@ -642,7 +644,7 @@ function up2k_init(subtle) {
else files = e.target.files; else files = e.target.files;
if (!files || !files.length) if (!files || !files.length)
return alert('no files selected??'); return toast.err(0, 'no files selected??');
more_one_file(); more_one_file();
var bad_files = [], var bad_files = [],
@ -710,9 +712,9 @@ function up2k_init(subtle) {
for (var a = 0; a < Math.min(20, missing.length); a++) for (var a = 0; a < Math.min(20, missing.length); a++)
msg.push(missing[a]); msg.push(missing[a]);
alert(msg.join('\n-- ')); return modal.alert(msg.join('\n-- '), function () {
dirs = []; read_dirs(rd, [], [], good, bad, spins);
pf = []; });
} }
spins = 0; spins = 0;
} }
@ -777,16 +779,22 @@ function up2k_init(subtle) {
if (good_files.length - bad_files.length <= 1 && ANDROID) if (good_files.length - bad_files.length <= 1 && ANDROID)
msg += '\nFirefox-Android has a bug which prevents selecting multiple files. Try selecting one file at a time. For more info, see firefox bug 1456557'; msg += '\nFirefox-Android has a bug which prevents selecting multiple files. Try selecting one file at a time. For more info, see firefox bug 1456557';
alert(msg); return modal.alert(msg, function () {
gotallfiles(good_files, []);
});
} }
var msg = ['upload these ' + good_files.length + ' files?']; var msg = ['upload these ' + good_files.length + ' files?'];
for (var a = 0, aa = Math.min(20, good_files.length); a < aa; a++) for (var a = 0, aa = Math.min(20, good_files.length); a < aa; a++)
msg.push(good_files[a][1]); msg.push(good_files[a][1]);
if (ask_up && !fsearch && !confirm(msg.join('\n'))) if (ask_up && !fsearch)
return; return modal.confirm(msg.join('\n'), function () { up_them(good_files); }, null);
up_them(good_files);
}
function up_them(good_files) {
var seen = {}, var seen = {},
evpath = get_evpath(), evpath = get_evpath(),
draw_each = good_files.length < 50; draw_each = good_files.length < 50;
@ -1147,7 +1155,7 @@ function up2k_init(subtle) {
return tasker(); return tasker();
} }
alert('y o u b r o k e i t\nfile: ' + t.name + '\nerror: ' + err); toast.err(0, 'y o u b r o k e i t\nfile: ' + t.name + '\nerror: ' + err);
}; };
reader.readAsArrayBuffer( reader.readAsArrayBuffer(
bobslice.call(t.fobj, car, cdr)); bobslice.call(t.fobj, car, cdr));
@ -1301,7 +1309,8 @@ function up2k_init(subtle) {
if (!response || !response.hits || !response.hits.length) { if (!response || !response.hits || !response.hits.length) {
smsg = '404'; smsg = '404';
msg = 'not found on server <a href="#" onclick="fsearch_explain()" class="fsearch_explain">(explain)</a>'; msg = ('not found on server <a href="#" onclick="fsearch_explain(' +
(has(perms, 'write') ? '0' : '1') + ')" class="fsearch_explain">(explain)</a>');
} }
else { else {
smsg = 'found'; smsg = 'found';
@ -1348,7 +1357,7 @@ function up2k_init(subtle) {
for (var a = 0; a < missing.length; a++) { for (var a = 0; a < missing.length; a++) {
var idx = t.hash.indexOf(missing[a]); var idx = t.hash.indexOf(missing[a]);
if (idx < 0) if (idx < 0)
return alert('wtf negative index for hash "{0}" in task:\n{1}'.format( return modal.alert('wtf negative index for hash "{0}" in task:\n{1}'.format(
missing[a], JSON.stringify(t))); missing[a], JSON.stringify(t)));
t.postlist.push(idx); t.postlist.push(idx);
@ -1437,7 +1446,7 @@ function up2k_init(subtle) {
tasker(); tasker();
return; return;
} }
alert("server broke; hs-err {0} on file [{1}]:\n".format( toast.err(0, "server broke; hs-err {0} on file [{1}]:\n".format(
xhr.status, t.name) + ( xhr.status, t.name) + (
(xhr.response && xhr.response.err) || (xhr.response && xhr.response.err) ||
(xhr.responseText && xhr.responseText) || (xhr.responseText && xhr.responseText) ||
@ -1497,7 +1506,7 @@ function up2k_init(subtle) {
console.log("ignoring dupe-segment error", t); console.log("ignoring dupe-segment error", t);
} }
else { else {
alert("server broke; cu-err {0} on file [{1}]:\n".format( toast.err(0, "server broke; cu-err {0} on file [{1}]:\n".format(
xhr.status, t.name) + (txt || "no further information")); xhr.status, t.name) + (txt || "no further information"));
return; return;
} }

View file

@ -1,302 +0,0 @@
#op_up2k {
padding: 0 1em 1em 1em;
}
#u2form {
position: absolute;
top: 0;
left: 0;
width: 2px;
height: 2px;
overflow: hidden;
}
#u2form input {
background: #444;
border: 0px solid #444;
outline: none;
}
#u2err.err {
color: #f87;
padding: .5em;
}
#u2err.msg {
color: #999;
padding: .5em;
font-size: .9em;
}
#u2btn {
color: #eee;
background: #555;
background: -moz-linear-gradient(top, #367 0%, #489 50%, #38788a 51%, #367 100%);
background: -webkit-linear-gradient(top, #367 0%, #489 50%, #38788a 51%, #367 100%);
background: linear-gradient(to bottom, #367 0%, #489 50%, #38788a 51%, #367 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#489', endColorstr='#38788a', GradientType=0);
text-decoration: none;
line-height: 1.3em;
border: 1px solid #222;
border-radius: .4em;
text-align: center;
font-size: 1.5em;
margin: .5em auto;
padding: .8em 0;
width: 16em;
cursor: pointer;
box-shadow: .4em .4em 0 #111;
}
#op_up2k.srch #u2btn {
background: linear-gradient(to bottom, #ca3 0%, #fd8 50%, #fc6 51%, #b92 100%);
text-shadow: 1px 1px 1px #fc6;
color: #333;
}
#u2conf #u2btn {
margin: -1.5em 0;
padding: .8em 0;
width: 100%;
max-width: 12em;
display: inline-block;
}
#u2conf #u2btn_cw {
text-align: right;
}
#u2notbtn {
display: none;
text-align: center;
background: #333;
padding-top: 1em;
}
#u2notbtn * {
line-height: 1.3em;
}
#u2tab {
margin: 3em auto;
width: calc(100% - 2em);
max-width: 100em;
}
#op_up2k.srch #u2tab {
max-width: none;
}
#u2tab td {
border: 1px solid #ccc;
border-width: 0 0px 1px 0;
padding: .1em .3em;
}
#u2tab td:nth-child(2) {
width: 5em;
white-space: nowrap;
}
#u2tab td:nth-child(3) {
width: 40%;
}
#op_up2k.srch td.prog {
font-family: sans-serif;
font-size: 1em;
width: auto;
}
#u2tab tbody tr:hover td {
background: #222;
}
#u2cards {
padding: 1em 0 .3em 1em;
margin: 1.5em auto -2.5em auto;
white-space: nowrap;
text-align: center;
overflow: hidden;
}
#u2cards.w {
width: 45em;
text-align: left;
}
#u2cards a {
padding: .2em 1em;
border: 1px solid #777;
border-width: 0 0 1px 0;
background: linear-gradient(to bottom, #333, #222);
}
#u2cards a:first-child {
border-radius: .4em 0 0 0;
}
#u2cards a:last-child {
border-radius: 0 .4em 0 0;
}
#u2cards a.act {
padding-bottom: .5em;
border-width: 1px 1px .1em 1px;
border-radius: .3em .3em 0 0;
margin-left: -1px;
background: linear-gradient(to bottom, #464, #333 80%);
box-shadow: 0 -.17em .67em #280;
border-color: #7c5 #583 #333 #583;
position: relative;
color: #fd7;
}
#u2cards span {
color: #fff;
}
#u2conf {
margin: 1em auto;
width: 30em;
}
#u2conf.has_btn {
width: 48em;
}
#u2conf * {
text-align: center;
line-height: 1em;
margin: 0;
padding: 0;
border: none;
outline: none;
}
#u2conf .txtbox {
width: 3em;
color: #fff;
background: #444;
border: 1px solid #777;
font-size: 1.2em;
padding: .15em 0;
height: 1.05em;
}
#u2conf .txtbox.err {
background: #922;
}
#u2conf a {
color: #fff;
background: #c38;
text-decoration: none;
border-radius: .1em;
font-size: 1.5em;
padding: .1em 0;
margin: 0 -1px;
width: 1.5em;
height: 1em;
display: inline-block;
position: relative;
bottom: -0.08em;
}
#u2conf input+a {
background: #d80;
}
#u2conf label {
font-size: 1.6em;
width: 2em;
height: 1em;
padding: .4em 0;
display: block;
border-radius: .25em;
}
#u2conf input[type="checkbox"] {
position: relative;
opacity: .02;
top: 2em;
}
#u2conf input[type="checkbox"]+label {
position: relative;
background: #603;
border-bottom: .2em solid #a16;
box-shadow: 0 .1em .3em #a00 inset;
}
#u2conf input[type="checkbox"]:checked+label {
background: #6a1;
border-bottom: .2em solid #efa;
box-shadow: 0 .1em .5em #0c0;
}
#u2conf input[type="checkbox"]+label:hover {
box-shadow: 0 .1em .3em #fb0;
border-color: #fb0;
}
#op_up2k.srch #u2conf td:nth-child(1)>*,
#op_up2k.srch #u2conf td:nth-child(2)>*,
#op_up2k.srch #u2conf td:nth-child(3)>* {
background: #777;
border-color: #ccc;
box-shadow: none;
opacity: .2;
}
#u2foot {
color: #fff;
font-style: italic;
}
#u2foot .warn {
font-size: 1.3em;
padding: .5em .8em;
margin: 1em -.6em;
color: #f74;
background: #322;
border: 1px solid #633;
border-width: .1em 0;
text-align: center;
}
#u2foot .warn span {
color: #f86;
}
html.light #u2foot .warn {
color: #b00;
background: #fca;
border-color: #f70;
}
html.light #u2foot .warn span {
color: #930;
}
#u2foot span {
color: #999;
font-size: .9em;
font-weight: normal;
}
#u2footfoot {
margin-bottom: -1em;
}
.prog {
font-family: monospace, monospace;
}
#u2tab a>span {
font-weight: bold;
font-style: italic;
color: #fff;
padding-left: .2em;
}
#u2cleanup {
float: right;
margin-bottom: -.3em;
}
.fsearch_explain {
padding-left: .7em;
font-size: 1.1em;
line-height: 0;
}
html.light #u2btn {
box-shadow: .4em .4em 0 #ccc;
}
html.light #u2cards span {
color: #000;
}
html.light #u2cards a {
background: linear-gradient(to bottom, #eee, #fff);
}
html.light #u2cards a.act {
color: #037;
background: inherit;
box-shadow: 0 -.17em .67em #0ad;
border-color: #09c #05a #eee #05a;
}
html.light #u2conf .txtbox {
background: #fff;
color: #444;
}
html.light #u2conf .txtbox.err {
background: #f96;
color: #300;
}
html.light #op_up2k.srch #u2btn {
border-color: #a80;
}
html.light #u2foot {
color: #000;
}
html.light #u2tab tbody tr:hover td {
background: #fff;
}

View file

@ -140,10 +140,10 @@ function import_js(url, cb) {
var script = mknod('script'); var script = mknod('script');
script.type = 'text/javascript'; script.type = 'text/javascript';
script.src = url; script.src = url;
script.onreadystatechange = cb;
script.onload = cb; script.onload = cb;
script.onerror = function () {
toast.err(0, 'Failed to load module:\n' + url);
};
head.appendChild(script); head.appendChild(script);
} }
@ -656,14 +656,24 @@ var tt = (function () {
})(); })();
function lf2br(txt) {
var html = '', hp = txt.split(/(?=<.?pre>)/i);
for (var a = 0; a < hp.length; a++)
html += hp[a].startsWith('<pre>') ? hp[a] :
hp[a].replace(/<br ?.?>\n/g, '\n').replace(/\n<br ?.?>/g, '\n').replace(/\n/g, '<br />\n');
return html;
}
var toast = (function () { var toast = (function () {
var r = {}, var r = {},
te = null, te = null,
visible = false,
obj = mknod('div'); obj = mknod('div');
obj.setAttribute('id', 'toast'); obj.setAttribute('id', 'toast');
document.body.appendChild(obj);; document.body.appendChild(obj);
r.visible = false;
r.hide = function (e) { r.hide = function (e) {
ev(e); ev(e);
@ -677,12 +687,7 @@ var toast = (function () {
if (ms) if (ms)
te = setTimeout(r.hide, ms * 1000); te = setTimeout(r.hide, ms * 1000);
var html = '', hp = txt.split(/(?=<.?pre>)/i); obj.innerHTML = '<a href="#" id="toastc">x</a>' + lf2br(txt);
for (var a = 0; a < hp.length; a++)
html += hp[a].startsWith('<pre>') ? hp[a] :
hp[a].replace(/<br ?.?>\n/g, '\n').replace(/\n<br ?.?>/g, '\n').replace(/\n/g, '<br />\n');
obj.innerHTML = '<a href="#" id="toastc">x</a>' + html;
obj.className = cl; obj.className = cl;
ms += obj.offsetWidth; ms += obj.offsetWidth;
obj.className += ' vis'; obj.className += ' vis';
@ -705,3 +710,118 @@ var toast = (function () {
return r; return r;
})(); })();
var modal = (function () {
var r = {},
q = [],
o = null,
cb_ok = null,
cb_ng = null;
r.busy = false;
r.show = function (html) {
o = mknod('div');
o.setAttribute('id', 'modal');
o.innerHTML = '<table><tr><td><div id="modalc">' + html + '</div></td></tr></table>';
document.body.appendChild(o);
document.addEventListener('keydown', onkey);
r.busy = true;
var a = ebi('modal-ng');
if (a)
a.onclick = ng;
var a = ebi('modal-ok');
if (a) {
a.onclick = ok;
a.focus();
}
var a = ebi('modali');
if (a)
a.focus();
};
r.hide = function () {
o.parentNode.removeChild(o);
document.removeEventListener('keydown', onkey);
r.busy = false;
setTimeout(next, 50);
};
function ok(e) {
ev(e);
var v = ebi('modali');
v = v ? v.value : true;
r.hide();
if (cb_ok)
cb_ok(v);
}
function ng(e) {
ev(e);
r.hide();
if (cb_ng)
cb_ng(null);
}
function onkey(e) {
if (e.code == 'Enter') {
var a = ebi('modal-ng');
if (a && document.activeElement == a)
return ng();
return ok();
}
if (e.code == 'Escape')
return ng();
}
function next() {
if (!r.busy && q.length)
q.shift()();
}
r.alert = function (html, cb) {
q.push(function () {
_alert(lf2br(html), cb);
});
next();
};
function _alert(html, cb) {
cb_ok = cb_ng = cb;
html += '<div id="modalb"><a href="#" id="modal-ok">OK</a></div>';
r.show(html);
}
r.confirm = function (html, cok, cng) {
q.push(function () {
_confirm(lf2br(html), cok, cng);
});
next();
}
function _confirm(html, cok, cng) {
cb_ok = cok;
cb_ng = cng === undefined ? cok : null;
html += '<div id="modalb"><a href="#" id="modal-ok">OK</a><a href="#" id="modal-ng">Cancel</a></div>';
r.show(html);
}
r.prompt = function (html, v, cok, cng) {
q.push(function () {
_prompt(lf2br(html), v, cok, cng);
});
next();
}
function _prompt(html, v, cok, cng) {
cb_ok = cok;
cb_ng = cng === undefined ? cok : null;
html += '<input id="modali" type="text" /><div id="modalb"><a href="#" id="modal-ok">OK</a><a href="#" id="modal-ng">Cancel</a></div>';
r.show(html);
ebi('modali').value = v || '';
}
return r;
})();