From 26458b7a0663a09e56392afcfbd1e221c6e2b9ea Mon Sep 17 00:00:00 2001 From: ed Date: Mon, 26 Jul 2021 22:40:55 +0200 Subject: [PATCH] keyboard file selection --- copyparty/web/browser.css | 30 ++++++++++++++++++++++++++++- copyparty/web/browser.js | 40 +++++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index f3e477ad..690d629c 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -294,6 +294,7 @@ html.light #ggrid a.sel { border-color: #c37; } #files tbody tr.sel:hover td, +#files tbody tr.sel:focus td, #ggrid a.sel:hover, html.light #ggrid a.sel:hover { color: #fff; @@ -328,6 +329,21 @@ html.light #ggrid a.sel { color: #fff; text-shadow: 0 0 1px #fff; } +#files tr:focus { + outline: none; + position: relative; +} +#files tr:focus td { + background: #111; + border-color: #fc0 #111 #fc0 #111; + box-shadow: 0 .2em 0 #fc0, 0 -.2em 0 #fc0; +} +#files tr:focus td:first-child { + box-shadow: -.2em .2em 0 #fc0, -.2em -.2em 0 #fc0; +} +#files tr:focus+tr td { + border-top: 1px solid transparent; +} #blocked { position: fixed; top: 0; @@ -1126,6 +1142,17 @@ html.light #files td { html.light #files tbody tr:last-child td { border-bottom: .2em solid #ccc; } +html.light #files tr:focus td { + background: #fff; + border-color: #c37; + box-shadow: 0 .2em 0 #e80 , 0 -.2em 0 #e80; +} +html.light #files tr:focus td:first-child { + box-shadow: -.2em .2em 0 #e80, -.2em -.2em 0 #e80; +} +html.light #files tr.sel td { + background: #925; +} html.light #files td:nth-child(2n) { color: #d38; } @@ -1179,7 +1206,8 @@ html.light #wnp { html.light #barbuf { background: none; } -html.light #files tr.sel:hover td { +html.light #files tr.sel:hover td, +html.light #files tr.sel:focus td { background: #c37; } html.light #files tr.sel td { diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index d5ebfd8d..8e38af7f 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -2011,8 +2011,9 @@ function tree_up() { document.onkeydown = function (e) { - if (!document.activeElement || document.activeElement != document.body && document.activeElement.nodeName.toLowerCase() != 'a') - return; + var ae = document.activeElement, aet = ''; + if (ae && ae != document.body) + aet = ae.nodeName.toLowerCase(); if (e.altKey || e.isComposing) return; @@ -2022,6 +2023,28 @@ document.onkeydown = function (e) { var k = e.code + '', pos = -1, n; + if (aet == 'tr' && ae.closest('#files')) { + var d = ''; + if (k == 'ArrowUp') d = 'previous'; + if (k == 'ArrowDown') d = 'next'; + if (d) { + var el = ae[d + 'ElementSibling']; + if (el) { + el.focus(); + document.documentElement.scrollTop += (d == 'next' ? 1 : -1) * el.offsetHeight; + return ev(e); + } + } + if (k == 'Space') { + clmod(ae, 'sel', 't'); + msel.selui(); + return ev(e); + } + } + + if (aet && aet != 'a') + return; + if (ctrl(e)) { if (k == 'KeyX') return fileman.cut(); @@ -3290,6 +3313,7 @@ var msel = (function () { r.sel.push(item); links[a].setAttribute('name', item.name); + links[a].closest('tr').setAttribute('tabindex', '0'); } }; @@ -3301,24 +3325,24 @@ var msel = (function () { r.load(); return r.all; }; - function selui() { + r.selui = function () { r.sel = r.all = null; clmod(ebi('wtoggle'), 'sel', r.getsel().length); thegrid.loadsel(); fileman.render(); } - function seltgl(e) { + r.seltgl = function (e) { ev(e); var tr = this.parentNode; clmod(tr, 'sel', 't'); - selui(); + r.selui(); } function evsel(e, fun) { ev(e); var trs = QSA('#files tbody tr'); for (var a = 0, aa = trs.length; a < aa; a++) clmod(trs[a], 'sel', fun); - selui(); + r.selui(); } ebi('selall').onclick = function (e) { evsel(e, "add"); @@ -3354,9 +3378,9 @@ var msel = (function () { r.render = function () { var tds = QSA('#files tbody td+td+td'); for (var a = 0, aa = tds.length; a < aa; a++) { - tds[a].onclick = seltgl; + tds[a].onclick = r.seltgl; } - selui(); + r.selui(); arcfmt.render(); fileman.render(); ebi('selzip').style.display = ebi('unsearch') ? 'none' : '';