Merge pull request #13875 from calixteman/xfa_focus

Annotation & XFA: Add focus outlines on different fields (bug 1723615, bug 1718528)
This commit is contained in:
calixteman 2021-08-05 20:09:00 +02:00 committed by GitHub
commit 834e475e1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 4 deletions

View File

@ -118,6 +118,9 @@ const MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2;
// the loop after having MAX_EMPTY_PAGES empty pages. // the loop after having MAX_EMPTY_PAGES empty pages.
const MAX_EMPTY_PAGES = 3; const MAX_EMPTY_PAGES = 3;
// Default value to start with for the tabIndex property.
const DEFAULT_TAB_INDEX = 5000;
function getBorderDims(node) { function getBorderDims(node) {
if (!node || !node.border) { if (!node || !node.border) {
return { w: 0, h: 0 }; return { w: 0, h: 0 };
@ -173,7 +176,12 @@ function* getContainedChildren(node) {
function setTabIndex(node) { function setTabIndex(node) {
while (node) { while (node) {
if (!node.traversal || node[$tabIndex]) { if (!node.traversal) {
node[$tabIndex] = node[$getParent]()[$tabIndex];
return;
}
if (node[$tabIndex]) {
return; return;
} }
@ -186,6 +194,7 @@ function setTabIndex(node) {
} }
if (!next || !next.ref) { if (!next || !next.ref) {
node[$tabIndex] = node[$getParent]()[$tabIndex];
return; return;
} }
@ -1755,6 +1764,8 @@ class Draw extends XFAObject {
} }
[$toHTML](availableSpace) { [$toHTML](availableSpace) {
setTabIndex(this);
if (this.presence === "hidden" || this.presence === "inactive") { if (this.presence === "hidden" || this.presence === "inactive") {
return HTMLResult.EMPTY; return HTMLResult.EMPTY;
} }
@ -2309,6 +2320,7 @@ class ExclGroup extends XFAObject {
} }
[$toHTML](availableSpace) { [$toHTML](availableSpace) {
setTabIndex(this);
if ( if (
this.presence === "hidden" || this.presence === "hidden" ||
this.presence === "inactive" || this.presence === "inactive" ||
@ -2611,6 +2623,8 @@ class Field extends XFAObject {
} }
[$toHTML](availableSpace) { [$toHTML](availableSpace) {
setTabIndex(this);
if (!this.ui) { if (!this.ui) {
// It's allowed to not have an ui, specs say: // It's allowed to not have an ui, specs say:
// If the UI element contains no children or is not present, // If the UI element contains no children or is not present,
@ -2642,7 +2656,6 @@ class Field extends XFAObject {
this.ui[$appendChild](node); this.ui[$appendChild](node);
} }
setTabIndex(this);
if ( if (
!this.ui || !this.ui ||
this.presence === "hidden" || this.presence === "hidden" ||
@ -4833,6 +4846,8 @@ class Subform extends XFAObject {
} }
[$toHTML](availableSpace) { [$toHTML](availableSpace) {
setTabIndex(this);
if (this.break) { if (this.break) {
// break element is deprecated so plug it on one of its replacement // break element is deprecated so plug it on one of its replacement
// breakBefore or breakAfter. // breakBefore or breakAfter.
@ -5255,7 +5270,7 @@ class Template extends XFAObject {
if (this.subform.children.length >= 2) { if (this.subform.children.length >= 2) {
warn("XFA - Several subforms in template node: please file a bug."); warn("XFA - Several subforms in template node: please file a bug.");
} }
this[$tabIndex] = 1000; this[$tabIndex] = DEFAULT_TAB_INDEX;
} }
[$isSplittable]() { [$isSplittable]() {

View File

@ -33,6 +33,8 @@ import {
import { AnnotationStorage } from "./annotation_storage.js"; import { AnnotationStorage } from "./annotation_storage.js";
import { ColorConverters } from "../shared/scripting_utils.js"; import { ColorConverters } from "../shared/scripting_utils.js";
const DEFAULT_TAB_INDEX = 1000;
/** /**
* @typedef {Object} AnnotationElementParameters * @typedef {Object} AnnotationElementParameters
* @property {Object} data * @property {Object} data
@ -722,6 +724,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
element.type = "text"; element.type = "text";
element.setAttribute("value", textContent); element.setAttribute("value", textContent);
} }
element.tabIndex = DEFAULT_TAB_INDEX;
elementData.userValue = textContent; elementData.userValue = textContent;
element.setAttribute("id", id); element.setAttribute("id", id);
@ -978,6 +981,7 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
element.setAttribute("checked", true); element.setAttribute("checked", true);
} }
element.setAttribute("id", id); element.setAttribute("id", id);
element.tabIndex = DEFAULT_TAB_INDEX;
element.addEventListener("change", function (event) { element.addEventListener("change", function (event) {
const name = event.target.name; const name = event.target.name;
@ -1052,6 +1056,7 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
element.setAttribute("checked", true); element.setAttribute("checked", true);
} }
element.setAttribute("id", id); element.setAttribute("id", id);
element.tabIndex = DEFAULT_TAB_INDEX;
element.addEventListener("change", function (event) { element.addEventListener("change", function (event) {
const { target } = event; const { target } = event;
@ -1148,6 +1153,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
selectElement.disabled = this.data.readOnly; selectElement.disabled = this.data.readOnly;
selectElement.name = this.data.fieldName; selectElement.name = this.data.fieldName;
selectElement.setAttribute("id", id); selectElement.setAttribute("id", id);
selectElement.tabIndex = DEFAULT_TAB_INDEX;
selectElement.style.fontSize = `${fontSize}px`; selectElement.style.fontSize = `${fontSize}px`;

View File

@ -95,6 +95,14 @@
border: 1px solid transparent; border: 1px solid transparent;
} }
.annotationLayer .textWidgetAnnotation input :focus,
.annotationLayer .textWidgetAnnotation textarea :focus,
.annotationLayer .choiceWidgetAnnotation select :focus,
.annotationLayer .buttonWidgetAnnotation.checkBox :focus,
.annotationLayer .buttonWidgetAnnotation.radioButton :focus {
outline: auto;
}
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:before, .annotationLayer .buttonWidgetAnnotation.checkBox input:checked:before,
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked:after, .annotationLayer .buttonWidgetAnnotation.checkBox input:checked:after,
.annotationLayer .buttonWidgetAnnotation.radioButton input:checked:before { .annotationLayer .buttonWidgetAnnotation.radioButton input:checked:before {

View File

@ -155,7 +155,13 @@
.xfaSelect:focus { .xfaSelect:focus {
background-image: none; background-image: none;
background-color: transparent; background-color: transparent;
outline: none; outline: auto;
outline-offset: -1px;
}
.xfaCheckbox:focus,
.xfaRadio:focus {
outline: auto;
} }
.xfaTextfield, .xfaTextfield,