Further keyboard UI accelerators.
This commit is contained in:
parent
e424fe9aa8
commit
56b939f6a2
|
@ -116,6 +116,19 @@ addEventListener("unload", e => {
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
navigate(e);
|
navigate(e);
|
||||||
break;
|
break;
|
||||||
|
case "ArrowLeft":
|
||||||
|
case "ArrowRight":
|
||||||
|
{
|
||||||
|
let focused = document.activeElement;
|
||||||
|
let all = [...focused.parentNode.querySelectorAll(".icon")];
|
||||||
|
let index = all.indexOf(focused);
|
||||||
|
if (index === -1) return;
|
||||||
|
index += e.code === "ArrowRight" ? 1 : -1;
|
||||||
|
if (index >= all.length) index = 0;
|
||||||
|
else if (index < 0) index = all.length -1;
|
||||||
|
all[index].focus();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
110
src/ui/ui.js
110
src/ui/ui.js
|
@ -471,6 +471,7 @@ var UI = (() => {
|
||||||
this.presets[preset.value] &&
|
this.presets[preset.value] &&
|
||||||
preset !== customizer._preset)) {
|
preset !== customizer._preset)) {
|
||||||
delete customizer._preset;
|
delete customizer._preset;
|
||||||
|
customizer.onkeydown = null;
|
||||||
customizer.remove();
|
customizer.remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -478,6 +479,7 @@ var UI = (() => {
|
||||||
customizer._preset = preset;
|
customizer._preset = preset;
|
||||||
row.classList.toggle("customizing", true);
|
row.classList.toggle("customizing", true);
|
||||||
let immutable = Permissions.IMMUTABLE[preset.value] || {};
|
let immutable = Permissions.IMMUTABLE[preset.value] || {};
|
||||||
|
let lastInput = null;
|
||||||
for (let input of customizer.querySelectorAll("input")) {
|
for (let input of customizer.querySelectorAll("input")) {
|
||||||
let type = input.value;
|
let type = input.value;
|
||||||
if (type in immutable) {
|
if (type in immutable) {
|
||||||
|
@ -486,35 +488,54 @@ var UI = (() => {
|
||||||
} else {
|
} else {
|
||||||
input.checked = perms.allowing(type);
|
input.checked = perms.allowing(type);
|
||||||
input.disabled = false;
|
input.disabled = false;
|
||||||
|
lastInput = input;
|
||||||
}
|
}
|
||||||
input.parentNode.classList.toggle("needed", this.siteNeeds(row._site, type));
|
input.parentNode.classList.toggle("needed", this.siteNeeds(row._site, type));
|
||||||
row.parentNode.insertBefore(customizer, row.nextElementSibling);
|
}
|
||||||
customizer.classList.toggle("closed", false);
|
|
||||||
customizer.onkeydown = e => {
|
row.parentNode.insertBefore(customizer, row.nextElementSibling);
|
||||||
let next = false;
|
customizer.classList.toggle("closed", false);
|
||||||
switch(e.code) {
|
let temp = preset.parentNode.querySelector("input.temp");
|
||||||
case "ArrowRight":
|
customizer.onkeydown = e => {
|
||||||
next = true;
|
|
||||||
case "ArrowUp":
|
switch(e.code) {
|
||||||
preset.focus();
|
case "Tab":
|
||||||
if (next) {
|
if (document.activeElement === lastInput) {
|
||||||
let temp = preset.parentNode.querySelector("input.temp");
|
if (temp) {
|
||||||
if (temp) temp.focus();
|
temp.tabIndex = "0";
|
||||||
else return false;
|
temp.onblur = () => this.customize(null);
|
||||||
|
setTimeout(() => temp.tabIndex = "-1", 50);
|
||||||
|
}
|
||||||
|
preset.focus();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
case "ArrowLeft":
|
||||||
|
case "ArrowRight":
|
||||||
|
case "ArrowUp":
|
||||||
this.onkeydown = null;
|
this.onkeydown = null;
|
||||||
this.customize(null);
|
this.customize(null);
|
||||||
e.preventDefault();
|
preset.focus();
|
||||||
return false;
|
switch(e.code.substring(5)) {
|
||||||
case "KeyT":
|
case "Left":
|
||||||
{
|
return false;
|
||||||
let temp = preset.parentNode.querySelector("input.temp");
|
case "Right":
|
||||||
if (temp) temp.checked = !temp.checked;
|
if (temp) {
|
||||||
|
temp.focus();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
case "KeyT":
|
||||||
|
{
|
||||||
|
let temp = preset.parentNode.querySelector("input.temp");
|
||||||
|
if (temp) temp.checked = !temp.checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.setTimeout(() => customizer.querySelector("input:not(:disabled)").focus(), 50);
|
|
||||||
}
|
}
|
||||||
|
window.setTimeout(() => customizer.querySelector("input:not(:disabled)").focus(), 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(sites = this.sites, sorter = this.sorter) {
|
render(sites = this.sites, sorter = this.sorter) {
|
||||||
|
@ -538,10 +559,33 @@ var UI = (() => {
|
||||||
let focused = document.activeElement;
|
let focused = document.activeElement;
|
||||||
if (!focused) return;
|
if (!focused) return;
|
||||||
let row = focused.closest("tr");
|
let row = focused.closest("tr");
|
||||||
if (row.matches(".customizer")) return;
|
if (!row || row.matches(".customizer")) return;
|
||||||
let dir = "next";
|
let dir = "next";
|
||||||
let newRow;
|
let newRow;
|
||||||
|
let mappedPreset = ({
|
||||||
|
"+": "TRUSTED",
|
||||||
|
"-": "UNTRUSTED",
|
||||||
|
"0": "DEFAULT",
|
||||||
|
"t": "T_TRUSTED",
|
||||||
|
"c": "CUSTOM"
|
||||||
|
})[e.key];
|
||||||
|
|
||||||
|
if (mappedPreset) {
|
||||||
|
let p = row.querySelector(`.preset[value='${mappedPreset}']`);
|
||||||
|
if (p) {
|
||||||
|
p.focus();
|
||||||
|
p.click();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch(e.code) {
|
switch(e.code) {
|
||||||
|
case "Delete":
|
||||||
|
case "Backspace":
|
||||||
|
row.querySelector(".preset[value='DEFAULT']").click();
|
||||||
|
e.preventDefault();
|
||||||
|
break;
|
||||||
case "Enter":
|
case "Enter":
|
||||||
case "Space":
|
case "Space":
|
||||||
if (focused.matches(".full-address")) {
|
if (focused.matches(".full-address")) {
|
||||||
|
@ -550,10 +594,9 @@ var UI = (() => {
|
||||||
if (e.code === "Enter") return; // let the popup handle closure
|
if (e.code === "Enter") return; // let the popup handle closure
|
||||||
let custom = row.querySelector(".preset[value='CUSTOM']");
|
let custom = row.querySelector(".preset[value='CUSTOM']");
|
||||||
custom.focus();
|
custom.focus();
|
||||||
|
custom.click();
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
break;
|
||||||
e.stopPropagation();
|
|
||||||
break;
|
|
||||||
case "Home":
|
case "Home":
|
||||||
newRow = row;
|
newRow = row;
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
|
@ -568,13 +611,19 @@ var UI = (() => {
|
||||||
|
|
||||||
if (newRow === row) {
|
if (newRow === row) {
|
||||||
let topButton = document.querySelector("#top > button");
|
let topButton = document.querySelector("#top > button");
|
||||||
if (top) topButton.focus();
|
if (topButton) topButton.focus();
|
||||||
} else {
|
} else {
|
||||||
newRow.querySelector("input.preset:checked").focus();
|
newRow.querySelector("input.preset:checked").focus();
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
break;
|
break;
|
||||||
|
case "KeyS":
|
||||||
|
row.querySelector(".https-only").click();
|
||||||
|
break;
|
||||||
|
case "KeyI":
|
||||||
|
UI.openSiteInfo(row.domain);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,13 +859,14 @@ var UI = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSecure(row, secure = !!row.querySelector("https-only:checked")) {
|
toggleSecure(row, secure = !!row.querySelector("https-only:checked")) {
|
||||||
this.customize(null);
|
|
||||||
let site = row.siteMatch;
|
let site = row.siteMatch;
|
||||||
site = site.replace(/^https?:/, secure ? "https:" : "http:");
|
site = site.replace(/^https?:/, secure ? "https:" : "http:");
|
||||||
if (site === row.siteMatch) {
|
if (site === row.siteMatch) {
|
||||||
site = Sites.toggleSecureDomainKey(site, secure);
|
site = Sites.toggleSecureDomainKey(site, secure);
|
||||||
}
|
}
|
||||||
if (site !== row.siteMatch) {
|
if (site !== row.siteMatch) {
|
||||||
|
this.customize(null);
|
||||||
|
let focused = document.activeElement;
|
||||||
let {policy} = UI;
|
let {policy} = UI;
|
||||||
policy.set(row.siteMatch, policy.DEFAULT);
|
policy.set(row.siteMatch, policy.DEFAULT);
|
||||||
policy.set(site, row.perms);
|
policy.set(site, row.perms);
|
||||||
|
@ -827,7 +877,11 @@ var UI = (() => {
|
||||||
}
|
}
|
||||||
let newRow = this.createSiteRow(site, site, row.perms, row.contextMatch, row.sitesCount);
|
let newRow = this.createSiteRow(site, site, row.perms, row.contextMatch, row.sitesCount);
|
||||||
row.parentNode.replaceChild(newRow, row);
|
row.parentNode.replaceChild(newRow, row);
|
||||||
newRow.querySelector(".https-only").focus();
|
if (focused) {
|
||||||
|
let selector = focused.matches(".preset[value]") ?
|
||||||
|
`.preset[value="${focused.value}"]` : ".https-only";
|
||||||
|
newRow.querySelector(selector).focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue