diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index e32c0968..5887c13f 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -1068,6 +1068,43 @@ html.light #ggrid a:hover { margin: 0; padding: 0; } +#rui { + position: fixed; + top: 0; + left: 0; + width: calc(100% - 2em); + height: auto; + overflow: auto; + max-height: calc(100% - 2em); + border-bottom: .5em solid #999; + background: #333; + padding: 1em; + z-index: 765; +} +#rui div+div { + margin-top: 1em; +} +#rui table { + width: 100%; +} +#rui td { + padding: .2em .5em; +} +#rui td+td, +#rui td input { + width: 100%; +} +#rui input[readonly] { + color: #fff; + background: #444; + border: 1px solid #777; + padding: .2em .25em; +} +#rui h1 { + margin: 0 0 .3em 0; + padding: 0; + font-size: 1.5em; +} #pvol, #barbuf, #barpos, diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index a536d8c8..57ce39e3 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -522,15 +522,14 @@ var mp = new MPlayer(); makeSortable(ebi('files'), mp.read_order.bind(mp)); -function get_np() { +function ft2dict(tr) { var th = ebi('files').tHead.rows[0].cells, - tr = QS('#files tr.play').cells, rv = [], ra = [], rt = {}; for (var a = 1, aa = th.length; a < aa; a++) { - var tv = tr[a].textContent, + var tv = tr.cells[a].textContent, tk = a == 1 ? 'file' : th[a].getAttribute('name').split('/').slice(-1)[0], vis = th[a].className.indexOf('min') === -1; @@ -541,6 +540,12 @@ function get_np() { rt[tk] = tv; } return [rt, rv, ra]; +} + + +function get_np() { + var tr = QS('#files tr.play'); + return ft2dict(tr); }; @@ -1499,28 +1504,87 @@ var fileman = (function () { base = vsp[0], ofn = uricom_dec(vsp[1])[0]; - var fn = prompt('new filename:', ofn); - if (!fn || fn == ofn) - return toast.warn(1, 'rename aborted'); - - var dst = base + uricom_enc(fn, false); - - function rename_cb() { - if (this.readyState != XMLHttpRequest.DONE) - return; - - if (this.status !== 200) { - var msg = this.responseText; - toast.err(9, 'rename failed:\n' + msg); - return; - } - toast.ok(2, 'rename OK'); - treectl.goto(get_evpath()); + var rui = ebi('rui'); + if (!rui) { + rui = mknod('div'); + rui.setAttribute('id', 'rui'); + document.body.appendChild(rui); } - var xhr = new XMLHttpRequest(); - xhr.open('GET', src + '?move=' + dst, true); - xhr.onreadystatechange = rename_cb; - xhr.send(); + var html = [ + '

rename file

', + '
', + '', + '', + '
old:
new:
', + '
', + '', + '|', + '', + '', + '', + '
', + '
' + ]; + + var vars = ft2dict(ebi(sel[0].id).closest('tr')), + keys = vars[1].concat(vars[2]); + + vars = vars[0]; + for (var a = 0; a < keys.length; a++) + html.push(''); + + html.push('
' + esc(keys[a]) + '
'); + rui.innerHTML = html.join('\n'); + var iold = ebi('rn_old'), + inew = ebi('rn_new'); + + function rn_reset() { + inew.value = iold.value; + inew.focus(); + inew.setSelectionRange(0, inew.value.lastIndexOf('.'), "forward"); + } + function rn_cancel() { + rui.parentNode.removeChild(rui); + } + + inew.onkeydown = function (e) { + if (e.key == 'Escape') + return rn_cancel(); + + if (e.key == 'Enter') + return rn_apply(); + }; + ebi('rn_cancel').onclick = rn_cancel; + ebi('rn_reset').onclick = rn_reset; + ebi('rn_apply').onclick = rn_apply; + ebi('rn_dec').onclick = function () { + inew.value = uricom_dec(inew.value)[0]; + }; + + iold.value = ofn; + rn_reset(); + + function rn_apply() { + var dst = base + uricom_enc(inew.value, false); + + function rename_cb() { + if (this.readyState != XMLHttpRequest.DONE) + return; + + if (this.status !== 200) { + var msg = this.responseText; + toast.err(9, 'rename failed:\n' + msg); + return; + } + toast.ok(2, 'rename OK'); + treectl.goto(get_evpath()); + rn_cancel(); + } + var xhr = new XMLHttpRequest(); + xhr.open('GET', src + '?move=' + dst, true); + xhr.onreadystatechange = rename_cb; + xhr.send(); + }; }; r.delete = function (e) {