Annotation & XFA: Add focus outlines on different fields (bug 1723615, bug 1718528)
- set a default tabindex to be sure they'll be taken into account in the TAB cycle (https://bugzilla.mozilla.org/show_bug.cgi?id=1723615). - show default outline when fields are focused (it was an a11y bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1718528).
This commit is contained in:
		
							parent
							
								
									4ad65c8b9c
								
							
						
					
					
						commit
						fef939d347
					
				@ -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]() {
 | 
				
			||||||
 | 
				
			|||||||
@ -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`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -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 {
 | 
				
			||||||
 | 
				
			|||||||
@ -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,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user