Accessibility/WebAccessibilityAPI: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
Line 45: Line 45:
   readonly attribute AccesibleElement? lastSibling;
   readonly attribute AccesibleElement? lastSibling;


   readony attribute Node? DOMNode;
   readony attribute Node or AccessibleSource? source;
};
};
</pre>
</pre>
Line 238: Line 238:


<code>
<code>
AccessibleElement .''DOMNode''
AccessibleElement .''source''
::Returns the DOM node associated with the accessible element if any. The accessible element does not have a DOM node, either when it has been unattached from the DOM node or it's not DOM node based. The first case happens when the javascript holds reference to the object longer than the object life cycle requires. The second case may happen because of browser-specific implementation or in javascript created trees.
::Returns the DOM node associated with the accessible element if any. The accessible element does not have a DOM node, either when it has been unattached from the DOM node or it's not DOM node based. The first case happens when the javascript holds reference to the object longer than the object life cycle. The second case happens because of browser-specific implementation or in javascript created trees. In case of JavaScript trees the ''source'' properties returns ''AccessibleSource'' instance used to create this accessible element.
</code>
</code>



Revision as of 18:45, 30 January 2015

Introduction

There's number of objectives on the web to improve accessibility and usability support. The web applications want to provide special support for their users, helping them navigate and perceive the content. The browser has number of add-ons that serve to improve accessibility support, for example, landmarks navigation. These tasks requires accessibility API similar to what desktop assistive technologies have.

Also web accessibility API allows in-browser automated accessibility testing of web content, i.e. helpful to check HTML and other standards in the browser is accessible to all users.

Web accessibility API

The API provides a generic accessibility interface that allows you to receive accessible object properties, traverse accessible hierarchy and interact with the accessible object. This interface can be requested from DOM node.

Node interface extension

DOM Node interface should be extended by

interface Node {
  AccessibleElement? accessibleElement;
};

Accessible element

This is basic interface implemented by all accessible objects.

interface AccessibleElement {
  readonly attribute DOMString role;

  boolean hasState(DOMString state);
  readonly attribute sequence<DOMString> states;

  readonly attribute DOMString name;
  readonly attribute DOMString description;
  readonly attribute DOMString value;
  readonly attribute Rect bounds;

  readonly attribute any getAttribute(in DOMString name);
  readonly attribute sequence<AccessibleElement>? getRelations(in DOMString type);

  readonly attribute sequence<DOMString> actions;
  void activate(in unsigned int actionIndex);

  readonly attribute AccesibleElement? parent;
  readonly attribute AccesibleElement? firstChild;
  readonly attribute AccesibleElement? lastChild;
  readonly attribute AccesibleElement? nextSibling;
  readonly attribute AccesibleElement? lastSibling;

  readony attribute Node or AccessibleSource? source;
};

Base properties

AccessibleElement .role

Returns accessible role as string. Examples: "button", "menu", "textfield".


AccessibleElement .hasState

Returns true if the accessible element has the given state. Examples of states: "focusable", "focused", "selectable".

AccessibleElement .states

Returns the list of states applied on the accessible element.


AccessibleElement .name

Returns accessible name.


AccessibleElement .description

Returns accessible description.


AccessibleElement .value

Returns accessible value if applicable.


AccessibleElement .bounds

Returns boundaries of the accessible element in client coordinates as Rect.

Attributes

The accessible element may support any of attributes outlined below. Also the accessible element may expose its own custom attribute sets.


AccessibleElement .getAttribute(in DOMString name)

Returns the attribute by name.

Attribute list

A typical accessible element may support the following attributes:

DOMString accessKey;

Returns access key associated with the accessible element like "alt+letter".

DOMString keyboardShortcut;

Returns keyboard shortcut used to activate the accessible element, like "ctrl+letter".


int groupSize;

Returns a number of items withing the group this accessible element belongs to. If no group then -1.

int indexInGroup;

Returns an index in the group this accessible element belongs to. If no group then -1.

int level;

Returns level in hierarchy the accessible element belongs to. -1 if doesn't belong to any hierarchy.


int minvalue;

Returns minimum possible value.

int maxvalue;

Returns maximum possible value;

int step;

Returns step value (iteration between next values).

Relations

sequence<AccessibleElement> .getRelations(in DOMString type)

Returns related accessible elements of the given relation type.

Relation types

This is a typical list of relation types that may be exposed by the accessible element. Note, the accessible element may support custom relations as well.

label for

Referred accessible element is an element that is labelled by this accessible element.

labelled by

Referred accessible element is a label for this accessible element.

Actions

The accessible element may support actions that can be invoked on it. For example, jump on link or press on button, or it can be generic actions like scroll or focus. Certain accessible actions may take extra parameters.

AccessibleElement .actions

Returns a list of actions exposed by the accessible element.


AccessibleElement .activate(in DOMString name, in optional any param)

Invokes the accessible action.
Parameters:
name
action name to invoke
param
used to provide extra context for the action

Performs the given accessible action on the accessible element.

Action list

activate

Exposed on accessible elements that may be activated. Accessible elements may use other names for this action to emphasise the semantics they expose. For example, jump on links, press on buttons, check and uncheck on checkboxes. Accessible element may provide more than one activation actions. For exmaple, tree item can provide select/unselect as its primary action and expand/collapse as secondary.

focus

Focus the accessible element. May be different from "activate" action, for example, in case of buttons where "activate" means press.

scroll

Scrolls the accessible element into view, optionally takes coordinates relative the element to scroll the view to
Parameter:
coord of Coordinates
directory Coordinates {
int x;
int y;
};


Parent-child relations

The interface provides a bunch of methods to provide access to parent/child relations between accessible elements.

AccessibleElement .parent

Returns the parent accessible element if any.


AccessibleElement .firstChild

Returns the first child accessible element if any.


AccessibleElement .lastChild

Returns the last child accessible element if any.


AccessibleElement .nextSibling

Returns the next sibling accessible element if any.


AccessibleElement .previousSibling

Returns the previous sibling accessible element if any.

Other

AccessibleElement .source

Returns the DOM node associated with the accessible element if any. The accessible element does not have a DOM node, either when it has been unattached from the DOM node or it's not DOM node based. The first case happens when the javascript holds reference to the object longer than the object life cycle. The second case happens because of browser-specific implementation or in javascript created trees. In case of JavaScript trees the source properties returns AccessibleSource instance used to create this accessible element.

Content traversal

This section describes how to traverse the accessible content, for example, if you need to navigate the document by headings or move through the paragraph by words. A key concept of content traversal is accessible position which points out to a "point" in the document content. A position can be at accessible element, for example, at focused button, before or after accessible element, or inside text of accessible element, for example, at the end of first line of the paragraph.

enum Direction { "forward",
                 "backward",
                 "cyclic forward",
                 "cyclic backward" 
};

enum FilterResult { true, // means 'accept'
                    false, // means 'skip'
                    "accept",
                    "reject",
                    "skip"
};
callback Filter = FilterResult (AccessibleElement);

enum TextUnit { "char", "word", "line" };

enum Positioner { "before", "at", "after", "inside start", "inside end" };

[Constructor(AccessibleElement root, AccessibleElement elm, Positioner where),
 Constructor(AccessiblePos pos)]
interface AccessiblePos {
  readonly attribute AccessibleElement? anchor;

  boolean move(Direction dir, Filter or TextUnit rule);

  DOMString getText(AccessiblePos pos);

  any getTextAttribute(DOMString name);
  readonly attribute sequence<any> textAttributes;
};

AccessiblePos .Constructor

Constructs the accessible position.
Parameters
root of AccessibleElement
root of subtree the position will belong to
elm of AccessibleElement
anchor accessible element of the position
where of Positioner
describes where position should be placed relative anchor element

AccessiblePos .Constructor

Constructs the accessible position equal to given position.
Parameters
pos of AccessiblePos
accessible position to copy


AccessiblePos .anchor

Returns the accessible element the position is contained by. If the position is at element then element itself.

Move through the content

AccessiblePos .move

Move the accessible position in the content. Returns true if succeeded.
Parameters
dir of Direction
direction the position will be moved in
rule of Filter or TextUnit
describes how position can be moved

Get text

AccessibleDocument .getText

Returns the text enclosed between this and given accessible positions.

Example how to get first line of the first encountered paragraph:

var startPos = new AccessiblePos(doc, doc);
startPos.move("forward", a => a.role == "paragraph");
var endPos = new AccessiblePos(startPos);
endPos.move("forward", "line");
var lineText = doc.getText(startPos, endPos);

Text attributes

AccessibleDocument .getTextAttribute

Returns text attribute by name at this accessible position.

AccessibleDocument .textAttributes

Returns all text attributes at this accessible position.

color

Text color

background-color

Background color of text

Caret and selection

Document accessible provides bunch of methods to control selection and caret.

dictionary AccessibleRange {
  AccessiblePos start;
  AccessiblePos end;
};

partial interface AccessibleDocument {
  attribute AccessiblePos caret;
  readonly attribute sequence<AccessibleRange> selections;
  void select(AccessiblePos start, AccessiblePos end);
  void addToSelection(AccessiblePos start, AccessiblePos end);
  void removeFromSelection(AccessiblePos start, AccessiblePos end);
};

AccessibleDocument .caret

Returns accessible position for the caret.

AccessibleDocument .selections

Returns list of accessible ranges for selected content. A range is pair of start and end accessible positions.

AccessibleDocument .select

Selects the content between given positions. Clears previous selection.

AccessibleDocument .addToSelection

Selects the content between given positions. Previously selected content stays selected.

AccessibleDocument .removeFromSelection

Unselects the content between given positions. The rest of selection is not touched.

Hit test

partial interface AccessibleDocument {
  AccessiblePos positionFromPoint(int x, int y);
};

AccessibleDocument .positionFromPoint

Returns accessible position at the given point in client coordinates.

Virtual cursor

Virtual cursor is accessible position attached to the accessible document. It's unique per document.

partial interface AccessibleDocument {
  AccesiblePos cursor;
};

Whenever the virtual cursor position is changed then cursor_moved event is fired.

Events

The accessible element may fire various number of events. You can add event listener on document accessible

interface AccessibleEvent {
  readonly attribute DOMString type;
  readonly attribute AccessibleElement target;
};

callback AccessibleEventListener (AccessibleEvent event);

partial interface AccessibleDocument {
  void addEventListener(AccessibleEventListener listener);
  void removeEventListener(AccessibleEventListener listener);
};

AccessibleDocument .addEventListener

Adds event listener.

AccessibleDocument .removeEventListener

Removes event listener.

Event types

"focus"

Fired when accessible element is focused.

JavaScript trees

The web developer can create accessible element tree right in JavaScript and attach it to existing accessible element. For example, if the author wants to make accessible charts drawn in a canvas then javascript accessible tree is a right thing for this. The accessible element should implement AccessibleSource interface which basically portrays AccessibleElement interface.

callback interface AccessilbeSource {
  readonly attribute DOMString role;
  readonly attribute sequence<DOMString> states;
  readonly attribute DOMString name;
  readonly attribute DOMString description;
  readonly attribute DOMString value;

  readonly attribute any getAttribute(in DOMString name);
  readonly attribute sequence<AccessibleElement>? getRelations(in DOMString type);

  readonly attribute sequence<DOMString> actions;
  void activate(DOMString action);
};

Attaching to the tree

partial interface AccessibleElement {
  void attachSource(AccessibleSource or sequence<AccessibleSource>);
  void removeSource(AccessibleSource or sequence<AccessibleSource>);
  void sourceChanged(DOMString prop);
};

AccessibleElement .attachSource

Creates accessible elements from given source elements and adds them as children of the accessible element.

AccessibleElement .removeSource

Removes accessible elements, generated from given source elements, from the accessible tree.

AccessibleElement .sourceChanged

Called when source has been changed and its property value should be reflected in host accessible element.

Example

Say you have a canvas with drawn button. In order to make it accessible you can create accessible button right in JS.

var buttonObj = {
  role: "button",
  states: "focusable",
  name: "test"
};

and then you simply attach the buttonObj to the accessible tree.

var canvas = document.getElementById("canvas").accessibleElement;
canvas.attachSource(buttonObj);

If accessible button property is changed then you have to call sourceChanged, for example, if name is changed then you do

buttonObj.name = "new name";
canvas.firstChild.sourceChanged("name");

Taxonomies

You can get hierarchical relations between roles, states or actions. For example, if the web author introduces a role 'x-checklistitem' that is compounded from two roles 'checkbox' and 'listitem' and supposed to inherit properties of both then the web author should integrate the new role into existing hierarchy.

partial interface AccessibleDocument {
  sequence<DOMString> getTaxonomy(in DOMString type, in DOMString value);
  void buildTaxonomy(in DOMString type, in DOMString newbie, in sequence<DOMString> base)
    raises(DOMException);
};
AccessibleDocument .getTaxonomy
    Returns a sequence of base items
    Parameters
      type
          a taxonomy type, supported values are 'role' or 'action'
      value
          a value the taxonomy is requested for

Returns a sequence of base item the given item is inherited from. For example, for 'checkmenuitem' role it will return 'checkbox' and 'menuitem' roles.

AccessibleDocument .buildTaxonomy
    Adds the item into hierarchy
    Parameters
      type
          a taxonomy type, like 'role' or 'action'
      newbie
          a new item put in hierarchy
      base
          a list of base items the new item is inherited from

Adds a new value into hierarchy. Example,

a11ydoc.buildTaxonomy('role', 'x-checklistitem', [ 'checkbox', 'menuitem' ]);

Extensibility

The web application might need to extend default taxonomies to express the new semantics. For example, the web service publishing music sheets can introduce new characteristics like role, states, etc to describe music sheet content. However the web application should take care to explain new characteristic by extending default taxonomies, i.e. by describing the connection between old and new characteristics. That will resolve any backward compatibility issue, so if the consumer doesn't know about new roles then he can still figure out a closest match it's aware about. For example, if the web app author introduces "x-redbutton' and provides a role taxonomy for it saying this is an extension of 'button' role, then the consumer unfamiliar with 'x-redbutton' role will treat it as a button.

The author should follow name convention to avoid potential collisions with future additions into the spec predefined lists. Thus all names should be prefixed by 'x-' like 'x-redbutton' from example above.

Music sheet example

To make a music sheet accessible the web app may introduce bunch of new roles, attributes and relations:

roles:
  'sheet' - inherited from 'section'
  'note' - inherited from 'image', describes the note
role 'sheet' attributes:
  instrument: DOMString,
  tempo: number/DOMString
  clef: DOMString
role 'note' attributes:
  key: enum { C, D, E, F, G, A, H },
  alteration: enum { none, flat, sharp },
  octave: enum { ... },
  duration: number,
  effects: sequence<DOMString>, // tremolo, bend
role 'note' relations:
  crescendo: [note, ...] a list a notes the crescendo is applied to
  diminuendo: [note, ...] a list a notes the diminuendo is applied to