2025-09-13 02:24:51 +02:00
|
|
|
class KeyboardModalHandler {
|
2023-07-02 23:28:02 +03:00
|
|
|
static setupFocusTrap() {
|
2025-09-13 02:24:51 +02:00
|
|
|
const container = document.getElementById("modal-container");
|
|
|
|
if (container !== null) {
|
|
|
|
container.onkeydown = (e) => {
|
|
|
|
if (e.key === 'Tab') {
|
|
|
|
// Since there is only one focusable button in the keyboard modal we always want to focus it with the tab key. This handles
|
|
|
|
// the special case of having just one focusable element in a dialog/ where keyboard focus is placed on an element that is not in the
|
|
|
|
// tab order.
|
|
|
|
container.querySelectorAll('button')[0].focus();
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
|
|
|
};
|
2023-07-02 23:28:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static open(fragment, initialFocusElementId) {
|
2025-09-13 02:24:51 +02:00
|
|
|
if (document.getElementById("modal-container") !== null){
|
2018-07-05 22:18:51 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-02 23:28:02 +03:00
|
|
|
this.activeElement = document.activeElement;
|
|
|
|
|
2024-03-20 23:59:37 +01:00
|
|
|
const container = document.createElement("div");
|
2018-07-05 22:18:51 -07:00
|
|
|
container.id = "modal-container";
|
2023-07-02 23:28:02 +03:00
|
|
|
container.setAttribute("role", "dialog");
|
2018-07-05 22:18:51 -07:00
|
|
|
container.appendChild(document.importNode(fragment, true));
|
|
|
|
document.body.appendChild(container);
|
|
|
|
|
2024-03-20 23:59:37 +01:00
|
|
|
const closeButton = document.querySelector("button.btn-close-modal");
|
2018-07-05 22:18:51 -07:00
|
|
|
if (closeButton !== null) {
|
|
|
|
closeButton.onclick = (event) => {
|
|
|
|
event.preventDefault();
|
2025-09-13 02:24:51 +02:00
|
|
|
KeyboardModalHandler.close();
|
2018-07-05 22:18:51 -07:00
|
|
|
};
|
|
|
|
}
|
2023-07-02 23:28:02 +03:00
|
|
|
|
2025-09-13 02:24:51 +02:00
|
|
|
const initialFocusElement = document.getElementById(initialFocusElementId);
|
2023-07-03 16:32:31 +03:00
|
|
|
if (initialFocusElement !== undefined) {
|
|
|
|
initialFocusElement.focus();
|
|
|
|
}
|
2023-07-02 23:28:02 +03:00
|
|
|
|
|
|
|
this.setupFocusTrap();
|
2018-07-05 22:18:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static close() {
|
2025-09-13 02:24:51 +02:00
|
|
|
const container = document.getElementById("modal-container");
|
2018-07-05 22:18:51 -07:00
|
|
|
if (container !== null) {
|
|
|
|
container.parentNode.removeChild(container);
|
2025-09-13 02:24:51 +02:00
|
|
|
if (this.activeElement !== undefined && this.activeElement !== null) {
|
|
|
|
this.activeElement.focus();
|
|
|
|
}
|
2023-07-02 23:28:02 +03:00
|
|
|
}
|
2018-07-05 22:18:51 -07:00
|
|
|
}
|
|
|
|
}
|