Add keytraps to keep focus within modal windows (re: #8004)

This commit is contained in:
Quincy Morgan
2020-10-01 11:15:32 -04:00
parent 27003d9e71
commit edb6ad00b8
2 changed files with 45 additions and 0 deletions
+9
View File
@@ -234,6 +234,15 @@ textarea.mixed::placeholder {
font-style: italic;
}
/* keytraps need to be invisible yet not be display:none or visibility:hidden */
.keytrap {
width: 0;
height: 0;
padding: 0;
margin: 0;
border: 0;
}
/* tables */
table {
background-color: #fff;
+36
View File
@@ -40,6 +40,11 @@ export function uiModal(selection, blocking) {
.append('div')
.attr('class', 'modal fillL');
modal
.append('input')
.attr('class', 'keytrap keytrap-first')
.on('focus.keytrap', moveFocusToLast);
if (!blocking) {
shaded.on('click.remove-modal', () => {
if (d3_event.target === this) {
@@ -65,6 +70,11 @@ export function uiModal(selection, blocking) {
.append('div')
.attr('class', 'content');
modal
.append('input')
.attr('class', 'keytrap keytrap-last')
.on('focus.keytrap', moveFocusToFirst);
if (animate) {
shaded.transition().style('opacity', 1);
} else {
@@ -72,4 +82,30 @@ export function uiModal(selection, blocking) {
}
return shaded;
function moveFocusToFirst() {
let node = modal
// there are additional rules about what's focusable, but this suits our purposes
.select('a, button, input:not(.keytrap), select, textarea')
.node();
if (node) {
node.focus();
} else {
d3_select(this).node().blur();
}
}
function moveFocusToLast() {
let nodes = modal
.selectAll('a, button, input:not(.keytrap), select, textarea')
.nodes();
if (nodes.length) {
nodes[nodes.length - 1].focus();
} else {
d3_select(this).node().blur();
}
}
}