Skip to content

Commit 7f44f35

Browse files
committed
Make annotations focusable (bug 1851489)
When the annotation has a popup then the popup can be toggled in using the Enter key and hidden in using the Escape key.
1 parent b18a166 commit 7f44f35

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

src/display/annotation_layer.js

+22
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,9 @@ class AnnotationElement {
206206

207207
const container = document.createElement("section");
208208
container.setAttribute("data-annotation-id", data.id);
209+
if (!(this instanceof WidgetAnnotationElement)) {
210+
container.tabIndex = DEFAULT_TAB_INDEX;
211+
}
209212

210213
// The accessibility manager will move the annotation in the DOM in
211214
// order to match the visual ordering.
@@ -1969,6 +1972,8 @@ class PopupAnnotationElement extends AnnotationElement {
19691972
class PopupElement {
19701973
#dateTimePromise = null;
19711974

1975+
#boundKeyDown = this.#keyDown.bind(this);
1976+
19721977
#boundHide = this.#hide.bind(this);
19731978

19741979
#boundShow = this.#show.bind(this);
@@ -2044,6 +2049,11 @@ class PopupElement {
20442049
}
20452050
}
20462051

2052+
// Attach the event listener to toggle the popup with the keyboard.
2053+
for (const element of elements) {
2054+
element.container?.addEventListener("keydown", this.#boundKeyDown);
2055+
}
2056+
20472057
this.#container.hidden = true;
20482058
if (open) {
20492059
this.#toggle();
@@ -2187,6 +2197,16 @@ class PopupElement {
21872197
return p;
21882198
}
21892199

2200+
#keyDown(event) {
2201+
if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) {
2202+
return;
2203+
}
2204+
2205+
if (event.key === "Enter" || (event.key === "Escape" && this.#pinned)) {
2206+
this.#toggle();
2207+
}
2208+
}
2209+
21902210
/**
21912211
* Toggle the visibility of the popup.
21922212
*/
@@ -2195,9 +2215,11 @@ class PopupElement {
21952215
if (this.#pinned) {
21962216
this.#show();
21972217
this.#container.addEventListener("click", this.#boundToggle);
2218+
this.#container.addEventListener("keydown", this.#boundKeyDown);
21982219
} else {
21992220
this.#hide();
22002221
this.#container.removeEventListener("click", this.#boundToggle);
2222+
this.#container.removeEventListener("keydown", this.#boundKeyDown);
22012223
}
22022224
}
22032225

test/integration/annotation_spec.js

+61
Original file line numberDiff line numberDiff line change
@@ -527,4 +527,65 @@ describe("ResetForm action", () => {
527527
});
528528
});
529529
});
530+
531+
describe("Toggle popup with keyboard", () => {
532+
describe("tagged_stamp.pdf", () => {
533+
let pages;
534+
535+
beforeAll(async () => {
536+
pages = await loadAndWait(
537+
"tagged_stamp.pdf",
538+
"[data-annotation-id='20R']"
539+
);
540+
});
541+
542+
afterAll(async () => {
543+
await closePages(pages);
544+
});
545+
546+
it("must check that the popup has the correct visibility", async () => {
547+
await Promise.all(
548+
pages.map(async ([browserName, page]) => {
549+
let hidden = await page.$eval(
550+
"[data-annotation-id='21R']",
551+
el => el.hidden
552+
);
553+
expect(hidden).withContext(`In ${browserName}`).toEqual(true);
554+
await page.focus("[data-annotation-id='20R']");
555+
await page.keyboard.press("Enter");
556+
await page.waitForTimeout(10);
557+
hidden = await page.$eval(
558+
"[data-annotation-id='21R']",
559+
el => el.hidden
560+
);
561+
expect(hidden).withContext(`In ${browserName}`).toEqual(false);
562+
563+
await page.keyboard.press("Enter");
564+
await page.waitForTimeout(10);
565+
hidden = await page.$eval(
566+
"[data-annotation-id='21R']",
567+
el => el.hidden
568+
);
569+
expect(hidden).withContext(`In ${browserName}`).toEqual(true);
570+
571+
await page.keyboard.press("Enter");
572+
await page.waitForTimeout(10);
573+
hidden = await page.$eval(
574+
"[data-annotation-id='21R']",
575+
el => el.hidden
576+
);
577+
expect(hidden).withContext(`In ${browserName}`).toEqual(false);
578+
579+
await page.keyboard.press("Escape");
580+
await page.waitForTimeout(10);
581+
hidden = await page.$eval(
582+
"[data-annotation-id='21R']",
583+
el => el.hidden
584+
);
585+
expect(hidden).withContext(`In ${browserName}`).toEqual(true);
586+
})
587+
);
588+
});
589+
});
590+
});
530591
});

0 commit comments

Comments
 (0)