mirror of
https://github.com/9001/copyparty.git
synced 2026-01-12 07:44:08 -07:00
Add right-click menu (#1135)
This commit is contained in:
parent
8551472bf0
commit
82c496092f
|
|
@ -4125,3 +4125,46 @@ html.e #doc {
|
|||
html.e #detree {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#rcm {
|
||||
position: absolute;
|
||||
display: none;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--bg-u3);
|
||||
outline: none;
|
||||
border-radius: .3rem;
|
||||
box-shadow: 0 0 .3rem var(--bg-d3);
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
#rcm > * {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#rcm > a {
|
||||
padding: .2rem .3rem;
|
||||
}
|
||||
|
||||
#rcm > .hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rcm > a:hover {
|
||||
background: var(--bg-d2);
|
||||
}
|
||||
|
||||
#rcm > .sep {
|
||||
margin: 0 .2rem;
|
||||
border-bottom: 1px solid var(--a-gray);
|
||||
}
|
||||
|
||||
#tempname {
|
||||
color: var(--fg);
|
||||
background: var(--txt-bg);
|
||||
border: none;
|
||||
box-shadow: 0 0 2px var(--txt-sh);
|
||||
border-bottom: 1px solid #999;
|
||||
border-color: var(--a);
|
||||
border-radius: .2em;
|
||||
padding: .2em .3em;
|
||||
}
|
||||
|
|
@ -129,6 +129,8 @@
|
|||
|
||||
<div id="widget"></div>
|
||||
|
||||
<div id="rcm" tabindex="0"></div>
|
||||
|
||||
<script>
|
||||
var SR = "{{ r }}",
|
||||
CGV1 = {{ cgv1 }},
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ if (1)
|
|||
"cl_reset": "reset",
|
||||
"cl_hpick": "tap on column headers to hide in the table below",
|
||||
"cl_hcancel": "column hiding aborted",
|
||||
"cl_rcm": "right-click menu",
|
||||
|
||||
"ct_grid": '田 the grid',
|
||||
"ct_ttips": '◔ ◡ ◔">ℹ️ tooltips',
|
||||
|
|
@ -265,6 +266,7 @@ if (1)
|
|||
"cdt_lim": "max number of files to show in a folder",
|
||||
"cdt_ask": "when scrolling to the bottom,$Ninstead of loading more files,$Nask what to do",
|
||||
"cdt_hsort": "how many sorting rules (<code>,sorthref</code>) to include in media-URLs. Setting this to 0 will also ignore sorting-rules included in media links when clicking them",
|
||||
"cdt_ren": "enable custom right-click menu, you can still access the regular menu by pressing the shift key and right-clicking",
|
||||
|
||||
"tt_entree": "show navpane (directory tree sidebar)$NHotkey: B",
|
||||
"tt_detree": "show breadcrumbs$NHotkey: B",
|
||||
|
|
@ -640,6 +642,22 @@ if (1)
|
|||
"ur_um": "Finished;\n{0} uploads OK,\n{1} uploads failed, sorry",
|
||||
"ur_sm": "Finished;\n{0} files found on server,\n{1} files NOT found on server",
|
||||
|
||||
"rc_opn": "Open",
|
||||
"rc_ply": "Play",
|
||||
"rc_pla": "Play as audio",
|
||||
"rc_txt": "Open in file viewer",
|
||||
"rc_md": "Open in markdown editor",
|
||||
"rc_dl": "Download",
|
||||
"rc_zip": "Download as archive",
|
||||
"rc_del": "Delete",
|
||||
"rc_cut": "Cut",
|
||||
"rc_cpy": "Copy",
|
||||
"rc_pst": "Paste",
|
||||
"rc_nfo": "New folder",
|
||||
"rc_nfi": "New file",
|
||||
"rc_sal": "Select all",
|
||||
"rc_sin": "Invert selection",
|
||||
|
||||
"lang_set": "refresh to make the change take effect?",
|
||||
};
|
||||
|
||||
|
|
@ -966,6 +984,7 @@ ebi('op_cfg').innerHTML = (
|
|||
' </div>\n' +
|
||||
'</div>\n' +
|
||||
'<div><h3>' + L.cl_keytype + '</h3><div><select id="key_notation"></select></div></div>\n' +
|
||||
(!MOBILE ? '<div><h3>' + L.cl_rcm + '</h3><div><a id="ren" class="tgl btn" href="#" tt="' + L.cdt_ren + '">enable</a></div></div>' : '') +
|
||||
'<div><h3>' + L.cl_hiddenc + ' ' + (MOBILE ? '<a href="#" id="hcolsh">' + L.cl_hidec + '</a> / ' : '') + '<a href="#" id="hcolsr">' + L.cl_reset + '</a></h3><div id="hcols"></div></div>'
|
||||
);
|
||||
|
||||
|
|
@ -995,6 +1014,34 @@ QS('#op_mkdir input[type="submit"]').value = L.ab_mkdir;
|
|||
QS('#op_new_md input[type="submit"]').value = L.ab_mkdoc;
|
||||
QS('#op_msg input[type="submit"]').value = L.ab_msg;
|
||||
|
||||
// right-click menu
|
||||
ebi('rcm').innerHTML = (
|
||||
'<a href="#" id="ropn">' + L.rc_opn + '</a>' +
|
||||
'<a href="#" id="rply">' + L.rc_ply + '</a>' +
|
||||
'<a href="#" id="rpla">' + L.rc_pla + '</a>' +
|
||||
'<a href="#" id="rtxt">' + L.rc_txt + '</a>' +
|
||||
'<a href="#" id="rmd">' + L.rc_md + '</a>' +
|
||||
'<div id="rs1" class="sep"></div>' +
|
||||
'<a href="#" id="rdl">' + L.rc_dl + '</a>' +
|
||||
(have_zip ?
|
||||
'<a href="#" id="rzip">' + L.rc_zip + '</a>'
|
||||
: '') +
|
||||
'<div id="rs2" class="sep"></div>' +
|
||||
(has(perms, "move") ?
|
||||
'<a href="#" id="rdel">' + L.rc_del + '</a>' +
|
||||
'<a href="#" id="rcut">' + L.rc_cut + '</a>'
|
||||
: '') +
|
||||
'<a href="#" id="rcpy">' + L.rc_cpy + '</a>' +
|
||||
(has(perms, "write") ?
|
||||
'<a href="#" id="rpst">' + L.rc_pst + '</a>' +
|
||||
'<div id="rs3" class="sep"></div>' +
|
||||
'<a href="#" id="rnfo">' + L.rc_nfo + '</a>' +
|
||||
'<a href="#" id="rnfi">' + L.rc_nfi + '</a>'
|
||||
: '') +
|
||||
'<div id="rs4" class="sep"></div>' +
|
||||
'<a href="#" id="rsal">' + L.rc_sal + '</a>' +
|
||||
'<a href="#" id="rsin">' + L.rc_sin + '</a>'
|
||||
);
|
||||
|
||||
(function () {
|
||||
var ops = QSA('#ops>a');
|
||||
|
|
@ -9395,6 +9442,212 @@ ebi('files').onclick = ebi('docul').onclick = function (e) {
|
|||
};
|
||||
|
||||
|
||||
|
||||
var rcm = (function () {
|
||||
if (MOBILE)
|
||||
return {enabled: false}
|
||||
|
||||
var r = {
|
||||
enabled: true
|
||||
};
|
||||
bcfg_bind(r, 'enabled', 'ren', true);
|
||||
|
||||
var menu = ebi('rcm');
|
||||
var selFile = {
|
||||
elem: null,
|
||||
type: null,
|
||||
path: null,
|
||||
id: null,
|
||||
relpath: null,
|
||||
no_dsel: false
|
||||
};
|
||||
|
||||
function mktemp(is_dir) {
|
||||
var row = mknod('tr', 'temp',
|
||||
'<td>-new-</td>' +
|
||||
'<td colspan="' + (QSA("#files thead th").length - 1) + '"><input id="tempname" class="i" type="text" placeholder="' + (is_dir ? 'Folder' : "File") + ' Name"></td>'
|
||||
);
|
||||
QS("#files tbody").appendChild(row);
|
||||
|
||||
function sendit(name) {
|
||||
name = ('' + name).trim();
|
||||
if (!name)
|
||||
return;
|
||||
var data = new FormData();
|
||||
data.set("act", is_dir ? "mkdir" : "new_md");
|
||||
data.set("name", name);
|
||||
|
||||
var req = new XHR();
|
||||
req.open("POST", get_evpath());
|
||||
req.onload = req.onerror = function() {
|
||||
if (req.status == 405 || req.status == 500)
|
||||
return toast.err(3, "a " + (is_dir ? "folder" : "file") + " with that name already exists.");
|
||||
if (req.status < 200 || req.status > 399)
|
||||
return toast.err(3, "couldn't create " + (is_dir ? "folder" : "file") + ": <br><code>" + esc(req.responseText) + '</code>');
|
||||
|
||||
location.reload();
|
||||
};
|
||||
req.send(data);
|
||||
}
|
||||
|
||||
var input = ebi("tempname");
|
||||
input.onblur = function() {
|
||||
sendit(input.value);
|
||||
// Chrome blurs elements when calling remove for some reason
|
||||
input.onblur = null;
|
||||
row.remove();
|
||||
};
|
||||
input.onkeydown = function(e) {
|
||||
if (e.key == "Enter")
|
||||
sendit(input.value);
|
||||
if (e.key == "Enter" || e.key == "Escape") {
|
||||
input.onblur = null;
|
||||
row.remove();
|
||||
ev(e);
|
||||
}
|
||||
};
|
||||
input.focus();
|
||||
}
|
||||
|
||||
var opts = QSA('#rcm a');
|
||||
for (var i = 0; i < opts.length; i++) {
|
||||
opts[i].onclick = function(e) {
|
||||
ev(e);
|
||||
switch(e.target.id.slice(1)) {
|
||||
case 'opn':
|
||||
var a = mknod('a');
|
||||
a.href = selFile.path;
|
||||
a.target = selFile.type == "dir" ? '' : '_blank';
|
||||
a.click();
|
||||
break;
|
||||
case 'ply':
|
||||
if (selFile.type == 'gf')
|
||||
thegrid.imshow(selFile.relpath);
|
||||
else
|
||||
play('f-' + selFile.id);
|
||||
break;
|
||||
case 'pla':
|
||||
play('f-' + selFile.id);
|
||||
break;
|
||||
case 'txt':
|
||||
location = '?doc=' + selFile.relpath;
|
||||
break;
|
||||
case 'md':
|
||||
location = selFile.path + '?v';
|
||||
break;
|
||||
case 'dl':
|
||||
ebi('seldl').click();
|
||||
break;
|
||||
case 'zip':
|
||||
ebi('selzip').click();
|
||||
break;
|
||||
case 'del':
|
||||
fileman.delete();
|
||||
break;
|
||||
case 'cut':
|
||||
fileman.cut();
|
||||
break;
|
||||
case 'cpy':
|
||||
fileman.cpy();
|
||||
break;
|
||||
case 'pst':
|
||||
fileman.paste();
|
||||
fileman.clip = [];
|
||||
break;
|
||||
case 'nfo':
|
||||
mktemp(true);
|
||||
break;
|
||||
case 'nfi':
|
||||
mktemp();
|
||||
break;
|
||||
case 'sal':
|
||||
msel.evsel(null, true);
|
||||
selFile.no_dsel = true;
|
||||
break;
|
||||
case 'sin':
|
||||
msel.evsel(null, 't');
|
||||
break;
|
||||
default:
|
||||
console.warn('Invalid rcm option "' + e.target.id + '"');
|
||||
}
|
||||
hide(true);
|
||||
};
|
||||
}
|
||||
|
||||
function show(x, y, target) {
|
||||
selFile.elem = selFile.type = selFile.path = selFile.id = selFile.relpath = null;
|
||||
selFile.no_dsel = false;
|
||||
if (target) {
|
||||
var file = target.closest("#files tbody tr");
|
||||
if (file) {
|
||||
selFile.no_dsel = clgot(file, "sel");
|
||||
clmod(file, "sel", true);
|
||||
selFile.elem = file;
|
||||
|
||||
selFile.path = basenames(file.children[1].firstChild.href).split('?')[0];
|
||||
selFile.relpath = selFile.path.split('/').slice(-1)[0];
|
||||
if (file.children[3].innerHTML == "---")
|
||||
selFile.type = "dir";
|
||||
else {
|
||||
var lead = file.firstChild.firstChild;
|
||||
selFile.id = lead.id.split('-')[1];
|
||||
selFile.type = lead.innerHTML[0] == '(' ? 'gf' : lead.id.split('-')[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
msel.selui();
|
||||
|
||||
var has_sel = msel.getsel().length;
|
||||
var has_clip = fileman.clip.length;
|
||||
|
||||
clmod(ebi('ropn'), 'hide', !selFile.path);
|
||||
clmod(ebi('rply'), 'hide', selFile.type != 'gf' && selFile.type != 'af');
|
||||
clmod(ebi('rpla'), 'hide', selFile.type != 'gf');
|
||||
clmod(ebi('rtxt'), 'hide', !selFile.id);
|
||||
clmod(ebi('rs1'), 'hide', !selFile.path);
|
||||
clmod(ebi('rmd'), 'hide', !selFile.id || selFile.path.slice(-3) != '.md');
|
||||
clmod(ebi('rdl'), 'hide', !has_sel);
|
||||
clmod(ebi('rzip'), 'hide', !has_sel);
|
||||
clmod(ebi('rs2'), 'hide', !has_sel);
|
||||
clmod(ebi('rcut'), 'hide', !has_sel);
|
||||
clmod(ebi('rdel'), 'hide', !has_sel);
|
||||
clmod(ebi('rcpy'), 'hide', !has_sel);
|
||||
clmod(ebi('rpst'), 'hide', !has_clip);
|
||||
clmod(ebi('rs3'), 'hide', !has_sel || !has_clip);
|
||||
|
||||
menu.style.left = x + 5 + 'px';
|
||||
menu.style.top = y + 5 + 'px';
|
||||
menu.style.display = 'block';
|
||||
menu.focus();
|
||||
}
|
||||
|
||||
function hide(force) {
|
||||
if (!menu.style.display || (!force && menu.contains(document.activeElement)))
|
||||
return;
|
||||
if (selFile.elem && !selFile.no_dsel)
|
||||
clmod(selFile.elem, "sel", false);
|
||||
selFile.elem = selFile.type = selFile.path = selFile.id = selFile.relpath = null;
|
||||
selFile.no_dsel = false;
|
||||
menu.style.display = '';
|
||||
}
|
||||
|
||||
ebi('wrap').oncontextmenu = function(e) {
|
||||
if (thegrid.en || !r.enabled || e.shiftKey || menu.style.display) {
|
||||
hide(true);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ev(e);
|
||||
show(e.clientX, e.clientY, e.target);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
menu.onblur = function() {setTimeout(hide)};
|
||||
|
||||
return r;
|
||||
})();
|
||||
|
||||
|
||||
function reload_mp() {
|
||||
if (mp && mp.au) {
|
||||
mpo.au = mp.au;
|
||||
|
|
|
|||
Loading…
Reference in a new issue