mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-19 14:48:08 +02:00
[Editor] Fix the role of the different editors in order to make them interactive elements (bug 1953290)
Having some interactive elements forces the screen readers to switch to form mode and consequently they delegate the keyboard stuff to the browser. This patch sets an aria label on each editor in order to have a better description than just 'application'.
This commit is contained in:
parent
bec6287b0a
commit
7fce3eac93
9 changed files with 41 additions and 35 deletions
|
@ -324,6 +324,19 @@ pdfjs-editor-signature-button =
|
|||
.title = Add signature
|
||||
pdfjs-editor-signature-button-label = Add signature
|
||||
|
||||
## Default editor aria labels
|
||||
|
||||
# “Highlight” is a noun, the string is used on the editor for highlights.
|
||||
pdfjs-editor-highlight-editor =
|
||||
.aria-label = Highlight editor
|
||||
# “Drawing” is a noun, the string is used on the editor for drawings.
|
||||
pdfjs-editor-ink-editor =
|
||||
.aria-label = Drawing editor
|
||||
pdfjs-editor-signature-editor =
|
||||
.aria-label = Signature editor
|
||||
pdfjs-editor-stamp-editor =
|
||||
.aria-label = Image editor
|
||||
|
||||
## Remove button for the various kind of editor.
|
||||
|
||||
pdfjs-editor-remove-ink-button =
|
||||
|
@ -360,10 +373,6 @@ pdfjs-editor-signature-add-signature-button-label = Add new signature
|
|||
pdfjs-free-text2 =
|
||||
.aria-label = Text Editor
|
||||
.default-content = Start typing…
|
||||
pdfjs-ink =
|
||||
.aria-label = Draw Editor
|
||||
pdfjs-ink-canvas =
|
||||
.aria-label = User-created image
|
||||
|
||||
## Alt-text dialog
|
||||
|
||||
|
|
|
@ -330,7 +330,7 @@ class AltText {
|
|||
button.append(tooltip);
|
||||
}
|
||||
|
||||
const element = this.#editor.getImageForAltText();
|
||||
const element = this.#editor.getElementForAltText();
|
||||
element?.setAttribute("aria-describedby", tooltip.id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1142,13 +1142,17 @@ class AnnotationEditor {
|
|||
* @returns {HTMLDivElement | null}
|
||||
*/
|
||||
render() {
|
||||
this.div = document.createElement("div");
|
||||
this.div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360);
|
||||
this.div.className = this.name;
|
||||
this.div.setAttribute("id", this.id);
|
||||
this.div.tabIndex = this.#disabled ? -1 : 0;
|
||||
const div = (this.div = document.createElement("div"));
|
||||
div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360);
|
||||
div.className = this.name;
|
||||
div.setAttribute("id", this.id);
|
||||
div.tabIndex = this.#disabled ? -1 : 0;
|
||||
div.setAttribute("role", "application");
|
||||
if (this.defaultL10nId) {
|
||||
div.setAttribute("data-l10n-id", this.defaultL10nId);
|
||||
}
|
||||
if (!this._isVisible) {
|
||||
this.div.classList.add("hidden");
|
||||
div.classList.add("hidden");
|
||||
}
|
||||
|
||||
this.setInForeground();
|
||||
|
@ -1156,23 +1160,22 @@ class AnnotationEditor {
|
|||
|
||||
const [parentWidth, parentHeight] = this.parentDimensions;
|
||||
if (this.parentRotation % 180 !== 0) {
|
||||
this.div.style.maxWidth = `${((100 * parentHeight) / parentWidth).toFixed(
|
||||
div.style.maxWidth = `${((100 * parentHeight) / parentWidth).toFixed(
|
||||
2
|
||||
)}%`;
|
||||
div.style.maxHeight = `${((100 * parentWidth) / parentHeight).toFixed(
|
||||
2
|
||||
)}%`;
|
||||
this.div.style.maxHeight = `${(
|
||||
(100 * parentWidth) /
|
||||
parentHeight
|
||||
).toFixed(2)}%`;
|
||||
}
|
||||
|
||||
const [tx, ty] = this.getInitialTranslation();
|
||||
this.translate(tx, ty);
|
||||
|
||||
bindEvents(this, this.div, ["pointerdown"]);
|
||||
bindEvents(this, div, ["keydown", "pointerdown"]);
|
||||
|
||||
if (this.isResizable && this._uiManager._supportsPinchToZoom) {
|
||||
this.#touchManager ||= new TouchManager({
|
||||
container: this.div,
|
||||
container: div,
|
||||
isPinchingDisabled: () => !this.isSelected,
|
||||
onPinchStart: this.#touchPinchStartCallback.bind(this),
|
||||
onPinching: this.#touchPinchCallback.bind(this),
|
||||
|
@ -1183,7 +1186,7 @@ class AnnotationEditor {
|
|||
|
||||
this._uiManager._editorUndoBar?.hide();
|
||||
|
||||
return this.div;
|
||||
return div;
|
||||
}
|
||||
|
||||
#touchPinchStartCallback() {
|
||||
|
@ -1692,7 +1695,6 @@ class AnnotationEditor {
|
|||
if (this.isResizable) {
|
||||
this.#createResizers();
|
||||
this.#resizersDiv.classList.remove("hidden");
|
||||
bindEvents(this, this.div, ["keydown"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1892,8 +1894,8 @@ class AnnotationEditor {
|
|||
/**
|
||||
* @returns {HTMLElement | null} the element requiring an alt text.
|
||||
*/
|
||||
getImageForAltText() {
|
||||
return null;
|
||||
getElementForAltText() {
|
||||
return this.div;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -111,6 +111,7 @@ class HighlightEditor extends AnnotationEditor {
|
|||
this.#methodOfCreation = params.methodOfCreation || "";
|
||||
this.#text = params.text || "";
|
||||
this._isDraggable = false;
|
||||
this.defaultL10nId = "pdfjs-editor-highlight-editor";
|
||||
|
||||
if (params.highlightId > -1) {
|
||||
this.#isFreeHighlight = true;
|
||||
|
|
|
@ -68,6 +68,7 @@ class InkEditor extends DrawingEditor {
|
|||
constructor(params) {
|
||||
super({ ...params, name: "inkEditor" });
|
||||
this._willKeepAspectRatio = true;
|
||||
this.defaultL10nId = "pdfjs-editor-ink-editor";
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
|
|
@ -79,6 +79,7 @@ class SignatureEditor extends DrawingEditor {
|
|||
this._willKeepAspectRatio = true;
|
||||
this.#signatureData = params.signatureData || null;
|
||||
this.#description = null;
|
||||
this.defaultL10nId = "pdfjs-editor-signature-editor";
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
@ -156,7 +157,6 @@ class SignatureEditor extends DrawingEditor {
|
|||
}
|
||||
|
||||
super.render();
|
||||
this.div.setAttribute("role", "figure");
|
||||
|
||||
if (this._drawId === null) {
|
||||
if (this.#signatureData) {
|
||||
|
@ -259,7 +259,7 @@ class SignatureEditor extends DrawingEditor {
|
|||
const { outline } = (this.#signatureData = data);
|
||||
this.#isExtracted = outline instanceof ContourDrawOutline;
|
||||
this.#description = description;
|
||||
this.div.setAttribute("aria-label", description);
|
||||
this.div.setAttribute("aria-description", description);
|
||||
let drawingOptions;
|
||||
if (this.#isExtracted) {
|
||||
drawingOptions = SignatureEditor.getDefaultDrawingOptions();
|
||||
|
|
|
@ -56,6 +56,7 @@ class StampEditor extends AnnotationEditor {
|
|||
super({ ...params, name: "stampEditor" });
|
||||
this.#bitmapUrl = params.bitmapUrl;
|
||||
this.#bitmapFile = params.bitmapFile;
|
||||
this.defaultL10nId = "pdfjs-editor-stamp-editor";
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
@ -353,7 +354,6 @@ class StampEditor extends AnnotationEditor {
|
|||
|
||||
super.render();
|
||||
this.div.hidden = true;
|
||||
this.div.setAttribute("role", "figure");
|
||||
|
||||
this.addAltTextButton();
|
||||
|
||||
|
@ -474,7 +474,7 @@ class StampEditor extends AnnotationEditor {
|
|||
action: "inserted_image",
|
||||
});
|
||||
if (this.#bitmapFileName) {
|
||||
canvas.setAttribute("aria-label", this.#bitmapFileName);
|
||||
this.div.setAttribute("aria-description", this.#bitmapFileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -686,11 +686,6 @@ class StampEditor extends AnnotationEditor {
|
|||
);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
getImageForAltText() {
|
||||
return this.#canvas;
|
||||
}
|
||||
|
||||
#serializeBitmap(toUrl) {
|
||||
if (toUrl) {
|
||||
if (this.#isSvg) {
|
||||
|
|
|
@ -184,7 +184,7 @@ describe("Signature Editor", () => {
|
|||
|
||||
// Check the aria label.
|
||||
await page.waitForSelector(
|
||||
`${editorSelector}[aria-label="Hello World"]`
|
||||
`${editorSelector}[aria-description="Hello World"]`
|
||||
);
|
||||
|
||||
// Edit the description.
|
||||
|
|
|
@ -361,9 +361,7 @@ describe("Stamp Editor", () => {
|
|||
await page.click(saveButtonSelector);
|
||||
|
||||
// Check that the canvas has an aria-describedby attribute.
|
||||
await page.waitForSelector(
|
||||
`${editorSelector} canvas[aria-describedby]`
|
||||
);
|
||||
await page.waitForSelector(`${editorSelector}[aria-describedby]`);
|
||||
|
||||
// Wait for the alt-text button to have the correct icon.
|
||||
await page.waitForSelector(`${buttonSelector}.done`);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue