function getView(provider: UserMenuProvider): UserMenuView {
if (!views.has(provider)) {
const view = provider.getView();
- getContainer().append(view.getElement());
+ const element = view.getElement();
+ getContainer().append(element);
+
+ element.addEventListener("shouldClose", () => close(provider));
views.set(provider, view);
}
import { escapeHTML } from "../../../StringUtil";
import * as DomChangeListener from "../../../Dom/Change/Listener";
import * as Language from "../../../Language";
+import { createFocusTrap, FocusTrap } from "focus-trap";
export class UserMenuView {
private readonly element: HTMLElement;
+ private readonly focusTrap: FocusTrap;
private readonly markAllAsReadButton: HTMLElement;
private readonly provider: UserMenuProvider;
name: "markAllAsRead",
title: Language.get("wcf.user.panel.markAllAsRead"),
});
+
+ this.focusTrap = createFocusTrap(this.element, {
+ allowOutsideClick: true,
+ escapeDeactivates: (): boolean => {
+ // Intercept the "Escape" key and close the dialog through other means.
+ this.element.dispatchEvent(new Event("shouldClose"));
+
+ return false;
+ },
+ fallbackFocus: this.element,
+ });
}
getElement(): HTMLElement {
}
async open(): Promise<void> {
- if (this.provider.isStale()) {
+ const isStale = this.provider.isStale();
+ if (isStale) {
this.reset();
+ }
- this.element.hidden = false;
+ this.element.hidden = false;
+ this.focusTrap.activate();
+ if (isStale) {
const data = await this.provider.getData();
this.setContent(data);
- } else {
- this.element.hidden = false;
}
}
close(): void {
+ this.focusTrap.deactivate();
+
this.element.hidden = true;
}
this.element.hidden = true;
this.element.classList.add("userMenu");
this.element.dataset.origin = this.provider.getPanelButton().id;
+ this.element.tabIndex = -1;
this.element.innerHTML = `
<div class="userMenuHeader">
<div class="userMenuTitle">${this.provider.getTitle()}</div>
function getView(provider) {
if (!views.has(provider)) {
const view = provider.getView();
- getContainer().append(view.getElement());
+ const element = view.getElement();
+ getContainer().append(element);
+ element.addEventListener("shouldClose", () => close(provider));
views.set(provider, view);
}
return views.get(provider);
-define(["require", "exports", "tslib", "../../../Date/Util", "../../../StringUtil", "../../../Dom/Change/Listener", "../../../Language"], function (require, exports, tslib_1, Util_1, StringUtil_1, DomChangeListener, Language) {
+define(["require", "exports", "tslib", "../../../Date/Util", "../../../StringUtil", "../../../Dom/Change/Listener", "../../../Language", "focus-trap"], function (require, exports, tslib_1, Util_1, StringUtil_1, DomChangeListener, Language, focus_trap_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserMenuView = void 0;
name: "markAllAsRead",
title: Language.get("wcf.user.panel.markAllAsRead"),
});
+ this.focusTrap = (0, focus_trap_1.createFocusTrap)(this.element, {
+ allowOutsideClick: true,
+ escapeDeactivates: () => {
+ // Intercept the "Escape" key and close the dialog through other means.
+ this.element.dispatchEvent(new Event("shouldClose"));
+ return false;
+ },
+ fallbackFocus: this.element,
+ });
}
getElement() {
return this.element;
}
async open() {
- if (this.provider.isStale()) {
+ const isStale = this.provider.isStale();
+ if (isStale) {
this.reset();
- this.element.hidden = false;
+ }
+ this.element.hidden = false;
+ this.focusTrap.activate();
+ if (isStale) {
const data = await this.provider.getData();
this.setContent(data);
}
- else {
- this.element.hidden = false;
- }
}
close() {
+ this.focusTrap.deactivate();
this.element.hidden = true;
}
getItems() {
this.element.hidden = true;
this.element.classList.add("userMenu");
this.element.dataset.origin = this.provider.getPanelButton().id;
+ this.element.tabIndex = -1;
this.element.innerHTML = `
<div class="userMenuHeader">
<div class="userMenuTitle">${this.provider.getTitle()}</div>
main: "lib/codemirror"
}],
shim: {
- 'focus-trap': { deps: ['tabbable'], exports: 'focus-trap' },
'perfect-scrollbar': { exports: 'PerfectScrollbar' },
'qr-creator': { exports: 'QrCreator' },
},