Accessibility/WebAccessibilityAPI: Difference between revisions

 
(31 intermediate revisions by the same user not shown)
Line 293: Line 293:
<code>
<code>
AccessibleElement .''actions''
AccessibleElement .''actions''
::Returns a [[#ActionSet|ActionSet]] object of actions exposed by the accessible element. The returned object is not live, i.e. it is not updated if the accessible element actions change.
::Returns a [[#ActionMap|ActionMap]] object of actions exposed by the accessible element. The returned object is not live, i.e. it is not updated if the accessible element actions change.
</code>
</code>


Line 374: Line 374:




<div id="ActionSet">
====ActionMap====


====ActionSet====
Accessible actions are presented by <code>ActionMap</code> map like object of pairs { action name, action object }.
</div>
 
Accessible actions are presented by <code>ActionSet</code> map like object of pairs { action name, action object }.


<pre>
<pre>
interface ActionSet {
interface ActionMap {
   readonly maplike<DOMString, Action>;
   readonly maplike<DOMString, Action>;
};
};
Line 477: Line 474:
                           });
                           });
</pre>
</pre>
====Questions/concerns====
* Interactions should be extended to allow to specify a control that triggers the action. The concept is described by InidieUI: you can use mouse, touchscreen, keyboard, voice control or a control element to invoke the action. Maybe Interactions should be renamed to Triggers to share terms with IndieUI.
Here's the image of InideUI action/interaction concept.
<div style="height: 254px; overflow: hidden;">
http://www.w3.org/WAI/intro/iui-scroll.png
</div>
Alternatively we could introduce relations between actions like "triggers" and "triggeredby".
* What about highlevel actions (uberactions), for example, "press" buttons means "send something somewhere". This may be covered by label. Another example, selected listitem on the left changes a view on the right, "select" actions has meaning of "change view". Or checkbox that enables/disables related controls, "check/uncheck" action means "enable/disable controls". These examples correlates to controlledby/controllerfor relations, but the relations doesn't reveal type of control.


===Parent-child relations===
===Parent-child relations===
Line 561: Line 573:
   AccessiblePos? move(DOMNode container, long offset);
   AccessiblePos? move(DOMNode container, long offset);
   AccessiblePos? move(DOMPoint);
   AccessiblePos? move(DOMPoint);
  AccessiblePos? move(Where where, Controller);


   AccessiblePos? search(Where where, Controller);
  AccessiblePos? move(Where where, Criteria);
   AccessiblePos? search(Where where, Criteria);


   readonly attribute AccessibleElement root;
   readonly attribute AccessibleElement root;
Line 576: Line 588:


====Construction====
====Construction====
Construction by accessible element and offset relative it.
<code>
<code>
AccessiblePos .''Constructor''(AccessibleElement, Offset, AccessibleElement)
AccessiblePos .''Constructor''(AccessibleElement, Offset, AccessibleElement)
Line 588: Line 603:
</code>
</code>


The offset may be either a number, a numeric mapping of caret position in the content, or a literal.


<pre>
<pre>
Line 593: Line 610:
enum OffsetLiterals {
enum OffsetLiterals {
   "before",
   "before",
   "afterbegin",
   "begin",
   "at",
   "at",
   "beforeend",
   "end",
   "after"
   "after"
};
};
Line 602: Line 619:
<code>
<code>
OffsetLiterals .''before''
OffsetLiterals .''before''
::Used to set the accessible position right before the accessible element beginning
::Used to set the accessible position right before the accessible element beginning.
</code>
</code>


<code>
<code>
OffsetLiterals .''afterbegin''
OffsetLiterals .''begin''
::Used to set the accessible position right after the accessible element beginning
::Used to set the accessible position right after the accessible element beginning.
</code>
</code>


<code>
<code>
OffsetLiterals .''at''
OffsetLiterals .''at''
::Used to set the accessible position at the accessible element
::Used to set the accessible position at the accessible element.
</code>
</code>


<code>
<code>
OffsetLiterals .''beforeend''
OffsetLiterals .''end''
::Used to set the accessible position right before the accessible element ending
::Used to set the accessible position right before the accessible element ending.
</code>
</code>


<code>
<code>
OffsetLiterals .''after''
OffsetLiterals .''after''
::Used to set the accessible position right after the accessible element ending
::Used to set the accessible position right after the accessible element ending.
</code>
</code>




<code>
<b>Example #1. Input widget.</b>
AccessiblePos .''Constructor''(DOMPoint, AccessibleElement)
 
::Constructs the accessible position.
<pre>
::Parameters
<input id="input" value="Hello">
:::''point'' of ''DOMPoint''
<script>
::::a point, the accessible position should be set at
var input = document.getElementById("input").a11ement;
:::''root'' of ''AccessibleElement'', optional
 
::::a root of subtree containing the position. If not provided then parent document is used.
// Position is at the control
</code>
var p = new A11ePos(input, "at");


// Position is in the control text at 0 offset.
p = new A11ePos(input, "begin");


<code>
// Position is in the control text at 5 offset.
AccessiblePos .''Constructor''(DOMNode, long, AccessibleElement)
p = new A11ePos(input, "end");
::Constructs the accessible position from (DOMNode, offset) pair.
</script>
::Parameters
</pre>
:::''node'' of ''DOMNode''
::::the container node
:::''offset'' of ''long''
::::offset within the container node
:::''root'' of ''AccessibleElement'', optional
::::a root of subtree containing the position. If not provided then parent document is used.
</code>


<b>Example #2. Image inside a paragraph.</b>


<code>
<pre>
AccessiblePos .''Constructor''
<p id="p">I <img id="img" src="love.png" alt="love"> you</p>
::Constructs the accessible position equal to given position.
::Parameters
:::''pos'' of ''AccessiblePos''
::::accessible position to copy
</code>


<script>
var img = document.getElementById("img").a11ement;


Examples:
// The position is right before the image, at 2 offset relative the paragraph.
<pre>
var p = new A11ePos(img, "before");
var pos1 = new A11ePos(new DOMPoint(x, y), document.accessibleElement);


var pos2 = new A11ePos(button.accessibleElement, "at");
// The position is right after the image, at 3 offset relative the paragraph.
var pos3 = new A11ePos(paragraph.accessibleElement, "afterbegin");
p = new A11ePos(img, "after");


var pos4 = new A11ePos(pos2);
// The position is at the image, no offset relative the paragraph is applicable.
p = new A11ePos(img, "at");
p = new A11ePos(img, "begin");
p = new A11ePos(img, "end");
</script>
</pre>
</pre>


====Move through the content====
<b>Example #3. Table.</b>
 
<pre>
<table id="table">
  <tr>
    <td>cell</td>
  </tr>
</table>
<script>
var table = document.getElementById("table").a11ement;


<code>
// The position at the table.
AccessiblePos .''move''(AccessilbeElement, Offset)
var p = new A11ePos(table, "at");
::Move the accessible position to the given anchor and offset.
 
::Parameters
// The position is in the table, before the row.
:::''element'' of ''AccessibleElement''
var p = new A11ePos(table, "begin");
::::the anchor
:::''offset'' of ''Offsest'', optional
::::offset relative the anchor
:::Return itself.


// The position is in the table, after the row.
var p = new A11ePos(table, "end");
// The position is in the table, before the row, numeric offset is ignored.
var p = new A11ePos(table, 1);
</script>
</pre>


AccessiblePos .''move''(DOMNode, long)
::Move the accessible position to the given DOM node at given offset.
::Parameters
:::''node'' of ''DOMNode''
::::the anchor
:::''offset'' of ''long''
::::offset relative the anchor
:::Return itself.


Construction from a point on the screen. See [[#Hit_testing|hit testing]] for details.


AccessiblePos .''move''(DOMPoint)
<code>
::Move the accessible position in the content. Returns true if succeeded.
AccessiblePos .''Constructor''(DOMPoint, AccessibleElement)
::Constructs the accessible position.
::Parameters
::Parameters
:::''point'' of ''DOMPoint''
:::''point'' of ''DOMPoint''
::::the point the accessible position should be moved to.
::::a point, the accessible position should be set at
:::Return itself.
:::''root'' of ''AccessibleElement'', optional
::::a root of subtree containing the position. If not provided then parent document is used.
</code>
 


Construction from a DOM node and offset relative it. See [[#Caret_and_selection|selection]] section for examples.
<code>
AccessiblePos .''Constructor''(DOMNode, long, AccessibleElement)
::Constructs the accessible position from (DOMNode, offset) pair.
::Parameters
:::''node'' of ''DOMNode''
::::the container node
:::''offset'' of ''long''
::::offset within the container node
:::''root'' of ''AccessibleElement'', optional
::::a root of subtree containing the position. If not provided then parent document is used.
</code>


AccessiblePos .''move''(Where, Controller)
::Move the accessible position to the content. Returns true if succeeded.
::Parameters
:::''where'' of ''Where''
::::where the search should be performed
:::''controller'' of ''Controller''
::::function describing a match
:::Return itself.


Copy constructor.


AccessiblePos .''search''(Where, Controller)
<code>
::Finds the accessible position relative the current one. Returns new instance.
AccessiblePos .''Constructor''
::Constructs the accessible position equal to given position.
::Parameters
::Parameters
:::''where'' of ''Where''
:::''pos'' of ''AccessiblePos''
::::where the search should be performed
::::accessible position to copy
:::''controller'' of ''Controller''
::::function describing a match
:::Return new instance.
</code>
</code>




<pre>
====Change the position====
enum Where { "forward",
 
            "backward",
There is a bunch of methods to change accessible position.
            "cyclic forward",
            "cyclic backward",
            "tofirst",
            "tolast",
            "left",
            "right",
            "up",
            "down",
            "above",
            "under",
            "closest"
};
</pre>


<code>
<code>
Where .''forward''
AccessiblePos .''move''(AccessilbeElement, Offset)
::Search after the accessible position.
::Move the accessible position to the given anchor and offset.
::Parameters
:::''element'' of ''AccessibleElement''
::::the anchor
:::''offset'' of ''Offsest'', optional
::::offset relative the anchor
:::Return itself or null if not succeeded.


Where .''backward''
::Search backwards from the accessible position.


Where .''cyclic forward''
AccessiblePos .''move''(DOMNode, long)
::Search forwards from the accessible position in cycle.
::Move the accessible position to the given DOM node at given offset.
::Parameters
:::''node'' of ''DOMNode''
::::the anchor
:::''offset'' of ''long''
::::offset relative the anchor
:::Return itself or null if not succeeded.


Where .''cyclic backward''
::Search backwards from the accessible position in cycle.


Where .''tofirst''
AccessiblePos .''move''(DOMPoint)
::Search for a first match inside the root.
::Move the accessible position in the content. Returns true if succeeded.
::Parameters
:::''point'' of ''DOMPoint''
::::the point the accessible position should be moved to.
:::Return itself or null if not succeeded.


Where .''tolast''
::Search backwards (from last to first element) for a first match inside the root.


Where .''left''
====Move through the content====
::Search for a match left to the position.


Where .''right''
Accessible position can be moved through the content by criteria.
::Search for a match right to the position.


Where .''up''
AccessiblePos .''move'' (''Where'', ''Criteria'')
::Search for a match up from the position.
::Move the accessible position to the content complying with criteria.
::Parameters
:::''where'' of ''Where''
::::where the search should be performed
:::''criteria'' of ''Criteria''
::::function describing a match
:::Return itself if succeeded, otherwise null.


Where .''down''
::Search for a match down from the position.


Where .''above''
AccessiblePos .''search'' (''Where'', ''Criteria'')
::Search for a match above the position.
::Search for content of the given criteria relative the accessible position.
::Parameters
:::''where'' of ''Where''
::::where the search should be performed
:::''criteria'' of ''Criteria''
::::function describing a match
:::Return new instance if succeeded, otherwise null.
</code>


Where .''under''
::Search for a match under the position.


Where .''closest''
=====Where to search=====
::Search for a geometrically closest match to the position.
</code>


The search area and the way accessible elements are traversed are defined by <code>Where</code> argument. It defines whether traversal is perfromed by accessible tree hierarchy or by layout on the screen, and whether the traversal is relative of the current position or relative of the root.


Examples:
<pre>
<pre>
function controller(elm) { }
enum Where {
var pos1 = new A11ePos(new DOMPoint(x, y), a11edoc).move("forward", controller);
  "forward",
  "backward",
  "cyclic forward",
  "cyclic backward",
  "tofirst",
  "tolast",


var pos2 = new A11ePos(elm, "at").move("backward", controller);
  "left",
 
  "right",
var pos3 = new A11ePos(pos).move("forward", controller);
  "up",
or
  "down",
var pos2 = pos2.search("forward", controller);
  "above",
  "under",
  "closest"
};
</pre>
</pre>


<code>
Where .''forward''
::Search after the accessible position.


Where .''backward''
::Search backwards from the accessible position.


=====Matching function=====
Where .''cyclic forward''
::Search forwards from the accessible position in cycle.


<pre>
Where .''cyclic backward''
callback Controller = SearchTerm sequence<SearchTerm> (AccessibleElement);
::Search backwards from the accessible position in cycle.
</pre>


Where .''first''
::Search for a first match inside the root.


<code>
Where .''last''
Controller
::Search backwards (from last to first element) for a first match inside the root.
::A matching function used to define an algorithm of how the position is moved through the document.
::Returns
:::a search term(s)
</code>


Where .''left''
::Search for a match left to the position.


<pre>
Where .''right''
enum SearchTerm {
::Search for a match right to the position.
  "char",
  "word",
  "sentence",
  "line",
  "paragraph",
  "change",
  "bit",


  "at",
Where .''up''
  "skipsubtree",
::Search for a match up from the position.
  "stop",
  "next"
};
</pre>


<code>
Where .''down''
SearchTerm .''char''
::Search for a match down from the position.
::Used to move the position one char long.
</code>


<code>
Where .''above''
SearchTerm .''word''
::Search for a match above the position.
::Used to move the position to the next word.
</code>


<code>
Where .''under''
SearchTerm .''sentence''
::Search for a match under the position.
::Used to move the position to the next sentence.
</code>


<code>
Where .''closest''
SearchTerm .''line''
::Search for a geometrically closest match to the position.
::Used to move the position to beginning of next line or end of previous line.
</code>
</code>


<code>
SearchTerm .''paragraph''
::Used to move the position to beginning of next/previous paragraph.
</code>


<code>
<b>Example.</b>
SearchTerm .''change''
::Used to move the position to next change either of text attribute or new accessible.
</code>


<code>
<pre>
SearchTerm .''bit''
function criteria(el) { }
::Used to move the position to next/previous navigable position. For example, from accessible start inside of it to right before accessible outside of it or moving from end of this line to start of next line in case of soft line break lines.
</code>


var pos1 = new A11ePos(new DOMPoint(x, y), a11edoc).move("forward", criteria);


<code>
var pos2 = new A11ePos(elm, "at").move("backward", criteria);
SearchTerm .''at''
::Used to set the position at the element. Search is stopped.


SearchTerm .''stop''
var pos3 = new A11ePos(pos).move("forward", criteria);
::Search is discontinued after other search terms are processed.
or
 
var pos2 = pos2.search("forward", criteria);
SearchTerm .''skipsubtree''
</pre>
::Subtree of traversed element is ignored for next step.


SearchTerm .''next''
::Used to continue the search if other search terms weren't succeed. Default option.
</code>


=====Criteria=====


<b>Examples.</b>
Criteria can be either a literal describing how the position should be moved or a matching function called for every traversed accessible.


<pre>
<pre>
var pos1 = new A11ePos(document.getElementById("a").a11ement);
typedef CriteriaLiteral or CriteriaFunc Criteria;
var pos2 = pos1.search("forward", () = > { return [ "word", "stop" ];});
var pos3 = pos1.search("forward", () => { return "word"; });
</pre>
</pre>


<pre>
<p>Click <a id="a">here</a>, fellow</p>
</pre>
pos2 and pos3 points after "here" word in the link.


<pre>
<pre>
<p>Click <a id="a"><img src=""></a>, fellow</p>
enum CriteriaLiteral {
  "char",
  "word",
  "sentence",
  "line",
  "paragraph",
  "change",
  "bit"
};
</pre>
</pre>
pos2 equals to pos1, pos3 points after "fellow" word in the link.


<code>
CriteriaLiteral .''char''
::Used to move the position one char long.


<b> Example. Navigate by widgets and structures, and by words in case of text.</b>
CriteriaLiteral .''word''
<pre>
::Used to move the position to the next word.
function controller(aEl)
{
  var role = document.taxonOf("role", aEl.role);
  if (role.is("widget")
    return [ "at", "skipsubtree" ];


  if (role.is("structure")
CriteriaLiteral .''sentence''
    return "at";
::Used to move the position to the next sentence.


  // Reenters with next accessible if it cannot move to the next word within this accessible.
CriteriaLiteral .''line''
  if (role.is("textcontainer"))
::Used to move the position to beginning of next line or end of previous line.
    return "word";


  return "next";
CriteriaLiteral .''paragraph''
}
::Used to move the position to beginning of next/previous paragraph.
 
CriteriaLiteral .''change''
::Used to move the position to next change either of text attribute or new accessible.


pos.move("next", finder);
CriteriaLiteral .''bit''
</pre>
::Used to move the position to next/previous navigable position. For example, from accessible start inside of it to right before accessible outside of it or moving from end of this line to start of next line in case of soft line break lines.
</code>


====Other methods====


<code>
<b>Example #1. Traverse a paragraph by words.</b>
AccessiblePos .''root''
::Returns the accessible element the position movement is restricted to.


AccessiblePos .''anchor''
<pre>
::Returns the accessible element the position is at or contained by.
var p = document.getElementById("p").a11ement;
var pos1 = new A11ePos(p, "begin", p), pos2 = null;
while (pos2 = pos1.search("forward", "word")) {
  console.log(pos2.text(pos1));
  pos1 = pos2;
}
</pre>


AccessiblePos .''offset''
<pre>
::Return an offset of the accessible position, either numeric or text.
<p id="p">Mozilla is a <a href="">free-software</a> community which
produces the <a href="">Firefox web browser</a>.</p>
</pre>


AccessiblePos .''toDOM''
The script above generates the log "Mozilla ", "is ", "a ", "free-", "software ", "community", "which ", "produces ", "the ", "Firefox ", "web ", "browser."
::Returns DOMRangeBound object which is a pair of DOM node and content offset relative it.
</code>


<pre>
<pre>
dictionary DOMRangeBound {
<p id="p">Mo<a href="">zilla</a>.</p>
  DOMNode node;
  long offset;
};
</pre>
</pre>


===Questions/concerns===
The log is "Mozilla".
 


* Do we need *is* method right on AccessibleElement or should we have Role interface having that method or should AccessibleElement return role taxa as a role.
<pre>
* Do we need to have "inContextOf" on AccessibleElement to check what the accessilbe belongs to. Note, native implementation doing some cache may be faster than tree traversal. If we need it then it's worth to consider *is* method too.
callback CriteriaFunc = CriteriaLiteral or Offset or "next" (AccessibleElement);
* Do we need isAnyOf() method additionally?
</pre>
* Yura: we should have async API for search.
 
* Do we need to compare() method to compare two positions
<code>
CriteriaFunc
::A criteria function used to define an algorithm of the match.
::Returns
:::a criteria term or offset(s)
</code>


===Virtual cursor===
If "next" is returned then criteria function is reentered with next traversed accessible. If offset is given then traversing is stopped, the accessible position is moved to the traversed accessible element and given offset. If criteria literal is returned then the accessible position is moved to the position complying the criteria. If it cannot be moved withing current accessible then it reenters with next accessible.


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


<b> Example. Navigate by widgets and structures, and by words in case of text.</b>
<pre>
<pre>
partial interface AccessibleDocument {
function criteria(aEl)
   AccesiblePos cursor;
{
};
   var role = document.taxonOf("role", aEl.role);
</pre>
  if (role.is("widget")
    return "at";


Whenever the virtual cursor position is changed then ''cursor_moved'' event is fired.
  if (role.is("structure")
    return "at";


Questions/concerns:
  // Reenters with next accessible if it cannot move to the next line within this accessible.
* Ensure that the virtual cursor is survivable. If it ends up in the hidden sub-tree for example. If subtee gets destroyed then cursor should be moved. If AccessiblePos doesn't have matching function then it's unclear where it should be moved.
  if (role.is("textcontainer"))
* Also take into account walking to/from parent/child frames
    return "line";
* Should it be outlined as moved?


==Text==
  return "next";
}


<pre>
pos.move("next", criteria);
partial interface AccessiblePos {
  DOMString textInBetween(AccessiblePos pos);
  readonly attribute AttributeSet textAttributes;
};
</pre>
</pre>
====Other methods====


<code>
<code>
AccessibleDocument .''textInBetween''
AccessiblePos .''root''
::Returns the text enclosed between this and given accessible positions.
::Returns the accessible element the position movement is restricted to.
</code>


Example how to get first line of the first encountered paragraph:
AccessiblePos .''anchor''
::Returns the accessible element the position is at or contained by.


<pre>
AccessiblePos .''offset''
var startPos = new A11ePos().move("first", a => a.role == "paragraph");
::Return an offset of the accessible position, either numeric or text.
var endPos = startPos && startPos.search("forward", a => [ "line", "stop" ]);
var text = startPos.textInBeetween(startPos, endPos);


say(text);
AccessiblePos .''toDOM''
</pre>
::Returns DOMRangeBound object which is a pair of DOM node and content offset relative it.
 
</code>
[ Promise variant if we had async API].


<pre>
<pre>
function getText() {
dictionary DOMRangeBound {
   var p = new A11ePos().move("first", a => a.role == "paragraph");
   DOMNode node;
   var startPos;
   long offset;
  return p.then(function(pos) {
};
    startPos = pos;
    return pos.search("forward", a => "line"); }).
  then(function(endPos) {
    return startPos.textInBetween(endPos);
  };
}
getText().then(function(text) { /* Say text */ })
</pre>
</pre>


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


<code>
<pre>
AccessibleDocument .''textAttributes''
partial interface AccessibleDocument {
::Returns a [[#AttributeSet|AttributeSet]] of all text attributes presented at this accessible position.
  AccesiblePos cursor;
</code>
};
</pre>


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


List of text attributes [to complete]
===Questions/concerns===


<code>
* Do we need *is* method right on AccessibleElement or should we have Role interface having that method or should AccessibleElement return role taxa as a role.
color
* Do we need to have "inContextOf" on AccessibleElement to check what the accessilbe belongs to. Note, native implementation doing some cache may be faster than tree traversal. If we need it then it's worth to consider *is* method too.
::Text color
* Do we need isAnyOf() method additionally?
* Do we need to compare() method to compare two positions
* Ensure that the virtual cursor is survivable. If it ends up in the hidden sub-tree for example. If subtee gets destroyed then cursor should be moved. If AccessiblePos doesn't have matching function then it's unclear where it should be moved.
* Also take into account walking to/from parent/child frames
* Should it be outlined as moved?
* Yura: we should have async API for search.


background-color
[ Promise variant if we had async API].
::Background color of text
</code>


<pre>
function getText() {
  var p = new A11ePos().move("first", a => a.role == "paragraph");
  var startPos;
  return p.then(function(pos) {
    startPos = pos;
    return pos.search("forward", a => "line"); }).
  then(function(endPos) {
    return startPos.textInBetween(endPos);
  };
}
getText().then(function(text) { /* Say text */ })
</pre>


<b>Example</b>
==Text==


<pre>
<pre>
<p id="p">hello <b>bold</b></p>
partial interface AccessiblePos {
  DOMString text(AccessiblePos pos);
  DOMString text(CriteriaLiteral criteria);
  readonly attribute AttributeSet textAttributes;
};
</pre>
 
<code>
AccessibleDocument .''text(AccessiblePos)''
::Returns the text enclosed between this and given accessible positions.
 
AccessibleDocument .''text(CriteriaLiteral)''
::Returns the text at the position complying the given criteria. See [[#Criteria|criteria]] for options.
</code>


var pos = new A11ePos(document.getElementById("p").a11ement, 7);
p.textAttributes.get("font-weight") == 700; // true
</pre>


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


==Caret and selection==
<pre>
function criteria(a)
  { return a.role == "paragraph" ? "being" : "next" };
var startPos = new A11ePos(document).move("first", criteria);
var endPos = startPos && startPos.search("forward", "line");
var text = startPos.text(startPos, endPos);
</pre>


Document accessible provides bunch of methods to operate on text selection and caret.
or same effect by using criteria literal


<pre>
<pre>
partial interface AccessibleDocument {
function criteria(a)
   attribute AccessiblePos caret;
   { return a.role == "paragraph" ? "being" : "next" };
  attribute AccessiblePos? selectionStart;
var pos = new A11ePos(document).move("first", criteria);
  attribute AccessiblePos? selectionEnd;
var text = pos.text("line");
};
</pre>
</pre>
===Text attributes===


<code>
<code>
AccessibleDocument .''caret''
AccessibleDocument .''textAttributes''
::Returns accessible position for the caret.
::Returns a [[#AttributeSet|AttributeSet]] of all text attributes presented at this accessible position.
</code>
</code>


List of text attributes [to complete]


<code>
<code>
AccessibleDocument .''selectionStart''
color
::Get/set selection start.
::Text color


 
background-color
AccessibleDocument .''selectionEnd''
::Background color of text
::Get/set selection end.
</code>
</code>


Line 1,065: Line 1,113:


<pre>
<pre>
var pos = new A11ePos(new DOMPoint(event.x, event.y));
<p id="p">hello <b>bold</b></p>
document.a11ement.selectionStart = pos;
 
var pos2 = new A11ePos(pos.anchor.nextSibling);
var pos = new A11ePos(document.getElementById("p").a11ement, 7);
document.a11ement.selectionEnd = pos;
p.textAttributes.get("font-weight") == 700; // true
</pre>
</pre>


<b>Example #2. Connection with DOM selection.</b>
==Caret and selection==
 
Document accessible provides bunch of methods to operate on text selection and caret.


<pre>
<pre>
var sel = window.getSelection();
partial interface AccessibleDocument {
var pos1 = new A11ePos(sel.anchorNode, sel.anchorOffset);
   attribute AccessiblePos caret;
var pos2 = new A11ePos(sel.focusNode, sel.focusOffset);
  attribute AccessiblePos? selectionStart;
 
   attribute AccessiblePos? selectionEnd;
var p1 = pos1.toDOM();
sel.getRangeAt(0).setStart(p1.node, p1.offset);
var p2 = pos2.toDOM();
sel.getRangeAt(0).setEnd(p2.node, p2.offset);
</pre>
 
==Geometry==
 
The section contains bunch of methods and approaches to deal with web page geometry.
 
===Outline===
 
AT can outline a position or a range enclosed between two positions. This feature is useful to track stuff like virtual cursor.
<pre>
partial interface AccessibleDocument {
   void outline(AccessiblePos pos1, optional AccessiblePos pos2);
   void clearOutlines();
};
};
</pre>
</pre>


<code>
<code>
AccessibleDocument .''outline''
AccessibleDocument .''caret''
::Outlines a position if second position is omitted. If second position is omitted then outlines a collapsed range.
::Returns accessible position for the caret.
 
AccessibleDocument .''clearOutlines''
::Removes all drawn outlines.
</code>
</code>


===Geometrical navigation===


AT can scan the web page by moving the position geometrically up/down/left/right.
<code>
<pre>
AccessibleDocument .''selectionStart''
var scanner
::Get/set selection start.
{
  start: function() {
    if (this.stopped)
      return;


    var nextpos = this.pos.move("right", this.controller);
AccessibleDocument .''selectionEnd''
    if (!nextpos)
::Get/set selection end.
      nextpos = this.pos.move("down", this.controller);
</code>


    if (nextpos) {
      document.outline(nextpos);
      window.setTimeout(this.start.bing(this), 1000);
    }
  },
  stop: function() {
    this.stopped = true;
  },


  controller: function(aEl) {
<b>Example.</b>
    var role = document.a11ement.taxonOf("role", aElm.role);
    if (role.is("widget"))
      return "at";


    return "next";
<pre>
  }
var pos = new A11ePos(new DOMPoint(event.x, event.y));
  pos: new A11ePos(new DOMPoint(0, 0)),
document.a11ement.selectionStart = pos;
  stopped: false
var pos2 = new A11ePos(pos.anchor.nextSibling);
}
document.a11ement.selectionEnd = pos;
</pre>
</pre>


===Hit testing===
<b>Example #2. Connection with DOM selection.</b>
 
The author can do accessible position to match the accessible element of given criteria at given position.


<pre>
<pre>
<script>
var sel = window.getSelection();
function onmove(aEvent)
var pos1 = new A11ePos(sel.anchorNode, sel.anchorOffset);
{
var pos2 = new A11ePos(sel.focusNode, sel.focusOffset);
  // Announce name of the accessible element pointed by mouse.
  var atcursor = new A11ePos(new DOMPoint(event.x, event.y));
  say(atcursor.anchor.name);


  // Locate a nearest control.
var p1 = pos1.toDOM();
  var atwidget = atcursor.search("closest", a => document.taxonOf("role", a.role).is("widget"));
sel.getRangeAt(0).setStart(p1.node, p1.offset);
  if (atwidget)
var p2 = pos2.toDOM();
    say(atwidget.name);
sel.getRangeAt(0).setEnd(p2.node, p2.offset);
};
</pre>
</script>


<body onmove="onmove(event);></body>
==Geometry==
</pre>


The section contains bunch of methods and approaches to deal with web page geometry.


Questions/concerns
===Outline===
*Outline: it's tricky to style that but maybe document or accessible should decide how it should be styled, for example, black outline on black background.
*Do we need a way to return coordinates of accessible position's edge points?
*Do we need a method to calculate distance between two positions?
*Do we need a method to calculate boundaries (aka containing rect)?
*Do we need a method to check whether the given point is contained by a range?
 
==Events==
 
The accessible element may fire various number of events. You can add event listener on document accessible to handle all events from accessible elements belonging to the document.


AT can outline a position or a range enclosed between two positions. This feature is useful to track stuff like virtual cursor.
<pre>
<pre>
callback AccessibleEventListener (AccessibleEvent event);
partial interface AccessibleDocument {
partial interface AccessibleDocument {
   void on(DOMString eventType, AccessibleEventListener listener);
   void outline(AccessiblePos pos1, optional AccessiblePos pos2);
   void off(DOMString eventType, AccessibleEventListener listener);
   void clearOutlines();
};
};
</pre>
</pre>


<code>
<code>
AccessibleDocument .''on''
AccessibleDocument .''outline''
::Adds event listener of the given event type.
::Outlines a position if second position is omitted. If second position is omitted then outlines a collapsed range.


AccessibleDocument .''off''
AccessibleDocument .''clearOutlines''
::Removes event listener of the given event type.
::Removes all drawn outlines.
</code>
</code>


===Geometrical navigation===


All event objects implement <code>AccessibleEvent</code> interface.
AT can scan the web page by moving the position geometrically up/down/left/right.
 
<pre>
<pre>
interface AccessibleEvent {
var scanner
   readonly attribute DOMString type;
{
  readonly attribute AccessibleElement target;
   start: function() {
  readonly attribute AttributeMap attributes;
    if (this.stopped)
};
      return;
</pre>


    var nextpos = this.pos.move("right", this.controller);
    if (!nextpos)
      nextpos = this.pos.move("down", this.controller);


<code>
    if (nextpos) {
AccessibleEvent .''type''
      document.outline(nextpos);
::Event type.
      window.setTimeout(this.start.bing(this), 1000);
    }
  },
  stop: function() {
    this.stopped = true;
  },


AccessibleEvent .''target''
  controller: function(aEl) {
::Event type accessible element target.
    var role = document.a11ement.taxonOf("role", aElm.role);
    if (role.is("widget"))
      return "at";


AccessibleEvent .''attributes''
    return "next";
::Extra attributes used to describe the event. Used for certain event types.
  }
</code>
  pos: new A11ePos(new DOMPoint(0, 0)),
  stopped: false
}
</pre>


===Hit testing===


<b>Example. Live regions processing.</b>
The author can do accessible position to match the accessible element of given criteria at given position.


<pre>
<pre>
function handleLiveRegion(aEvent)
<script>
function onmove(aEvent)
{
{
   var attrs =
  // Announce name of the accessible element pointed by mouse.
    { live: "assertive", relevant: "change:name" };
   var atcursor = new A11ePos(new DOMPoint(event.x, event.y));
  say(atcursor.anchor.name);
 
  // Locate a nearest control.
  var atwidget = atcursor.search("closest", a => document.taxonOf("role", a.role).is("widget"));
  if (atwidget)
    say(atwidget.name);
};
</script>


  if (aEvent.attributes.hasAllOf(attrs)) {
<body onmove="onmove(event);></body>
    say(aEvent.target.name);
  }
}
document.a11ement.on("change:name");
</pre>
</pre>




===Event types===
Questions/concerns
*Outline: it's tricky to style that but maybe document or accessible should decide how it should be styled, for example, black outline on black background.
*Do we need a way to return coordinates of accessible position's edge points?
*Do we need a method to calculate distance between two positions?
*Do we need a method to calculate boundaries (aka containing rect)?
*Do we need a method to check whether the given point is contained by a range?


[section needs to be completed]
==Events==


<code>
The accessible element may fire various number of events. You can add event listener on document accessible to handle all events from accessible elements belonging to the document.
"focus"
::Fired when accessible element is focused.


"caretmove"
<pre>
::Fired when caret is moved within the document.
callback AccessibleEventListener (AccessibleEvent event);


"change:name"
partial interface AccessibleDocument {
::Fired when name property is changed.
  void on(DOMString eventType, AccessibleEventListener listener);
</code>
  void off(DOMString eventType, AccessibleEventListener listener);
};
</pre>


<div id="Patterns">
<code>
AccessibleDocument .''on''
::Adds event listener of the given event type.


==Patterns==
AccessibleDocument .''off''
</div>
::Removes event listener of the given event type.
</code>


Controls may expose own patterns to expose their semantics if it cannot be expressed by accessible element properties.


===Value controls===
All event objects implement <code>AccessibleEvent</code> interface.
 
Control elements having numeric value like slider, progressbar, [https://html.spec.whatwg.org/multipage/forms.html#the-meter-element meter] or numberbox implement <code>AccessibleValue</code> inteface.


<pre>
<pre>
interface AccessibleValue {
interface AccessibleEvent {
   readonly attribute long max;
   readonly attribute DOMString type;
   readonly attribute long min;
   readonly attribute AccessibleElement target;
   readonly attribute long low;
   readonly attribute AttributeMap attributes;
  readonly attribute long high;
  readonly attribute long optimum;
  readonly attribute long step;
  readonly attribute long value;
};
};
</pre>
</pre>




===Group info===
<code>
AccessibleEvent .''type''
::Event type.


Item elements provides information about their group and their position in the group.
AccessibleEvent .''target''
::Event type accessible element target.


<pre>
AccessibleEvent .''attributes''
interface AccessibleGroupInfo {
::Extra attributes used to describe the event. Used for certain event types.
  readonly attribute long count;
</code>
  readonly attribute long index;
  readonly attribute long level;
};
</pre>




===Tables===
<b>Example. Live regions processing.</b>
 
A cell of tables and grids provide the interface for 2 dimensional navigation. Cell headers can be obtained by <code>labelledby</code> relation.


<pre>
<pre>
interface AccessibleTableCell {
function handleLiveRegion(aEvent)
   readonly attribute unsigned long rowIndex;
{
  readonly attribute unsigned long colIndex;
   var attrs =
    { live: "assertive", relevant: "change:name" };


   readonly attribute unsigned long rowSpan;
   if (aEvent.attributes.hasAllOf(attrs)) {
   readonly attribute unsigned long colSpan;
    say(aEvent.target.name);
};
   }
}
document.a11ement.on("change:name");
</pre>
</pre>




<code>
===Event types===
AccessibleTableCell .''rowIndex''
::Return row index of the cell.
 
AccessibleTableCell .''colIndex''
::Return column index of the cell.
</code>


[section needs to be completed]


<code>
<code>
AccessibleTableCell .''rowSpan''
"focus"
::Return number of rows that the cell is spanned to.
::Fired when accessible element is focused.


AccessibleTableCell .''colSpan''
"caretmove"
::Return number of columns that the cell is spanned to.
::Fired when caret is moved within the document.
 
"change:name"
::Fired when name property is changed.
</code>
</code>


<div id="Patterns">


==Multiprocessing==
==Patterns==
</div>


Accessible tree is scoped to a process, i.e. you can have seamless accessible tree between all document frames until it violates security policy. In case of multiprcess frames you have to use standard mechanism to communicate between processes.
Controls may expose own patterns to expose their semantics if it cannot be expressed by accessible element properties.


When the virtual cursor reaches a frame start or end and it was attempted to move it further then message is sent to a process where the virtual cursor would go in case of single process.
===Value controls===


Questions/concerns
Control elements having numeric value like slider, progressbar, [https://html.spec.whatwg.org/multipage/forms.html#the-meter-element meter] or numberbox implement <code>AccessibleValue</code> inteface.
* what messaging mechanism should be used
* should it be allowed to move from iframe to parent document?


<pre>
interface AccessibleValue {
  readonly attribute long max;
  readonly attribute long min;
  readonly attribute long low;
  readonly attribute long high;
  readonly attribute long optimum;
  readonly attribute long step;
  readonly attribute long value;
};
</pre>


<div id="JSSource">


==Make the content accessible==
===Group info===
</div>


You can tweak the accessible tree right in JS. You can do both:
Item elements provides information about their group and their position in the group.
* extend the native semantics of the DOM element by overriding its accessible properties,
* create whole accessible trees for inaccessible content, for example, for graphics, charts in a canvas.
 
===Direct change of accessible properties===
 
Accessible element properties can be altered right on the accessible element. Changing accessible property will result in accessible events if needed. For example:


<pre>
<pre>
<button id="button"></button>
interface AccessibleGroupInfo {
  readonly attribute long count;
  readonly attribute long index;
  readonly attribute long level;
};
</pre>


<script>
var div = document.getElementById("button").a11ement;
div.name = "click me";
div.description = "test accessibility";
</script>
</pre>


Accessible name and description are changed for the accessible button, "name changed" and "description changed" events are fired. Note, it changes neither visual appearance of the button nor DOM button element properties. If affects on accessible element of the button only.
===Tables===


====States====
A cell of tables and grids provide the interface for 2 dimensional navigation. Cell headers can be obtained by <code>labelledby</code> relation.


<pre>
<pre>
parital interface StateSet {
interface AccessibleTableCell {
   void set(DOMString ... states);
   readonly attribute unsigned long rowIndex;
   void unset(DOMString ... states);
   readonly attribute unsigned long colIndex;
   void toggle(DOMString state);
 
  readonly attribute unsigned long rowSpan;
   readonly attribute unsigned long colSpan;
};
};
</pre>
</pre>
Line 1,365: Line 1,384:


<code>
<code>
StateSet .''set''
AccessibleTableCell .''rowIndex''
::Set given states on the accessible element.
::Return row index of the cell.


StateSet .''unset''
AccessibleTableCell .''colIndex''
::Unset given states from the accessible element.
::Return column index of the cell.
 
StateSet .''toggle''
::Toggle the state on the accessible element.
</code>
</code>


<b>Example.</b>


<pre>
<code>
<div role="checkbox" onclick="disableEnable();">
AccessibleTableCell .''rowSpan''
<div role="listbox" id="listbox"/>
::Return number of rows that the cell is spanned to.
 
AccessibleTableCell .''colSpan''
::Return number of columns that the cell is spanned to.
</code>


<script>
function disableEnable()
{
  var listbox = document.getElementById("listbox").a11ement;
  listbox.states.toggle("disabled");
}
</script>
</pre>


====Attributes====
==Multiprocessing==


You can add/change/delete attributes on the accessible element. For example,
Accessible tree is scoped to a process, i.e. you can have seamless accessible tree between all document frames until it violates security policy. In case of multiprcess frames you have to use standard mechanism to communicate between processes.


<pre>
When the virtual cursor reaches a frame start or end and it was attempted to move it further then message is sent to a process where the virtual cursor would go in case of single process.
var listbox = document.getElementById("listbox").a11ement;
listbox.attributes.set("autocomplete", "list");
</pre>


====Relations====
Questions/concerns
* what messaging mechanism should be used
* should it be allowed to move from iframe to parent document?


<pre>
partial interface RelationMap {
  void add(DOMString relation, AccessibleElement element);
  void remove(DOMString relation, AccessibleElement element);
};
</pre>


<code>
<div id="JSSource">
RelationMap .''add''
 
::Puts the accessible element into relations.
==Make the content accessible==
</div>


RelationMap .''remove''
You can tweak the accessible tree right in JS. You can do both:
::Breaks the given relations between these accessible elements.
* extend the native semantics of the DOM element by overriding its accessible properties,
</code>
* create whole accessible trees for inaccessible content, for example, for graphics, charts in a canvas.


===Direct change of accessible properties===
Accessible element properties can be altered right on the accessible element. Changing accessible property will result in accessible events if needed. For example:


<pre>
<pre>
var label = document.getElementById("label");
<button id="button"></button>
var control = document.getElementById("control").a11ement;
 
control.relations.add("labelledby", label.a11yment);
<script>
var div = document.getElementById("button").a11ement;
div.name = "click me";
div.description = "test accessibility";
</script>
</pre>
</pre>


Accessible name and description are changed for the accessible button, "name changed" and "description changed" events are fired. Note, it changes neither visual appearance of the button nor DOM button element properties. If affects on accessible element of the button only.


[to do actions/interactions and patterns]
====States====
 
<pre>
parital interface StateSet {
  void set(DOMString ... states);
  void unset(DOMString ... states);
  void toggle(DOMString state);
};
</pre>




<div id="AccessibleSource">
<code>
===Extend the semantic via accessible source===
StateSet .''set''
</div>
::Set given states on the accessible element.


Alternatively you can extend native semantic of a DOM element by connecting it to an accessible source, the object describing accessible element. If the DOM node is not accessible then setting the accessible source on it makes it accessible. Otherwise the given source lands on top of the existing accessible object.
StateSet .''unset''
::Unset given states from the accessible element.


<pre>
StateSet .''toggle''
partial interface Node {
::Toggle the state on the accessible element.
  attribute AccessibleSource? accessibleSource;
</code>
};
</pre>


If the DOM node is accessible then you can provide accessible source by setting it up right in <code>AccessibleElement</code>.
<b>Example.</b>


<pre>
<pre>
partial interface AccessibleElement {
<div role="checkbox" onclick="disableEnable();">
   attribute AccessibleSource? source;
<div role="listbox" id="listbox"/>
};
 
<script>
function disableEnable()
{
   var listbox = document.getElementById("listbox").a11ement;
  listbox.states.toggle("disabled");
}
</script>
</pre>
</pre>


The source object used to describe the accessible element implements <code>AccessibleSource</code> interface which basically portrays properties of <code>AccessibleElement</code> interface.
====Attributes====
 
You can add/change/delete attributes on the accessible element. For example,


<pre>
<pre>
callback interface AccessibleSource {
var listbox = document.getElementById("listbox").a11ement;
  readonly attribute DOMString role;
listbox.attributes.set("autocomplete", "list");
  readonly attribute sequence<DOMString> states;
</pre>


  readonly attribute DOMString name;
====Relations====
  readonly attribute DOMString description;
  readonly attribute DOMString value;


   readonly attribute object attributes;
<pre>
   readonly attribute object relations;
partial interface RelationMap {
   void add(DOMString relation, AccessibleElement element);
   void remove(DOMString relation, AccessibleElement element);
};
</pre>


  readonly attribute sequence<DOMString> patterns;
<code>
  object toPattern(DOMString);
RelationMap .''add''
::Puts the accessible element into relations.


  readonly attribute DOMString text;
RelationMap .''remove''
  object textAttributesAt(Offset);
::Breaks the given relations between these accessible elements.
</code>


  readonly attribute object actions;
  void activate(DOMString action);


  AccessibleElement? element;
<pre>
};
var label = document.getElementById("label");
var control = document.getElementById("control").a11ement;
control.relations.add("labelledby", label.a11yment);
</pre>
</pre>




====Basics====
<div id="AccessibleSource">
===Extend the semantic via accessible source===
</div>


<code>
Alternatively you can extend native semantic of a DOM element by connecting it to an accessible source, the object describing accessible element. If the DOM node is not accessible then setting the accessible source on it makes it accessible. Otherwise the given source lands on top of the existing accessible object.
AccessibleSource .''role''


AccessibleSource .''states''
<pre>
partial interface Node {
  attribute AccessibleSource? accessibleSource;
};
</pre>


AccessibleSource .''name''
If the DOM node is accessible then you can provide accessible source by setting it up right in <code>AccessibleElement</code>.


AccessibleSource .''description''
AccessibleSource .''value''
::These properties corresponds to properties of ''AccessibleElement'' interface.
</code>
<b>Example #1. Override accessible name of the button.</b>
If the author needs to change accessible name of the HTML button
<pre>
<pre>
<button id="btn">press me</button>
partial interface AccessibleElement {
  attribute AccessibleSource? source;
};
</pre>
</pre>


then he can do this either with ARIA
The source object used to describe the accessible element implements <code>AccessibleSource</code> interface which basically portrays properties of <code>AccessibleElement</code> interface.
<pre>
document.getElementById("btn").setAttribute("aria-label", "new name");
</pre>


or set it directly on the accessible element
<pre>
<pre>
document.getElementById("btn").a11ement.name = "new name";
callback interface AccessibleSource {
</pre>
  readonly attribute DOMString role;
  readonly attribute sequence<DOMString> states;
 
  readonly attribute DOMString name;
  readonly attribute DOMString description;
  readonly attribute DOMString value;
 
  readonly attribute object attributes;
  readonly attribute object relations;


or by setting its accessible source
  readonly attribute sequence<DOMString> patterns;
  object toPattern(DOMString);


<pre>
  readonly attribute DOMString text;
document.getElementById("btn").accessibleSource = { name: "new name"; }
  object textAttributesAt(Offset);
</pre>


These are two equivalent approaches that can be used same time and mixed with each other the way that better fits the author's intent. It's important to keep in mind though that the accessible source has a priority over ARIA attributes. Setting up the accessible source doesn't operate on DOM and thus it's supposed to be more performant as extra layer is excluded between the author and accessibility engine. Another benefit of setting the accessible source is improved code readability since the author is able to point multiple properties at once in declarative way. For example,
  readonly attribute object actions;
  void activate(DOMString action);


<pre>
   AccessibleElement? element;
<script>
document.getElementById("btn").accessibleSource = {
   name: "new name",
  description: "new description",
  states: [ "disabled" ]
};
};
</script>
</pre>
</pre>




====Attributes and relations====
====Basics====


<code>
<code>
AccessibleSource .''attributes''
AccessibleSource .''role''
::A map of attribute names and their values applied to the accessible element
 
AccessibleSource .''relations''
AccessibleSource .''states''
::A map of relation types and relations for this accessible element. The bunch of types may be used to point out related elements. You can use either ''Node'', ''AccessibleElement'' or ''AccessibleSource'' objects. In latter case the object has to be in the accessible tree, in other words, it has to have associated accessible element when relation is poked by AT.
 
AccessibleSource .''name''
 
AccessibleSource .''description''
 
AccessibleSource .''value''
::These properties corresponds to properties of ''AccessibleElement'' interface.
</code>
</code>




<b> Example #2. Adding semantics.</b>
<b>Example #1. Override accessible name of the button.</b>


The accessible source can be also used when the author wants to add semantics to semantically neutral element. For example, the author can turn an ordinal HTML div element into listbox control:
If the author needs to change accessible name of the HTML button
<pre>
<pre>
<label id="label">Names:</label>
<button id="btn">press me</button>
<div id="list"></div>
</pre>


<script>
then he can do this either with ARIA
var listboxSource = {
<pre>
  role: "listbox",
document.getElementById("btn").setAttribute("aria-label", "new name");
  relations: {
    "labelledby": [ document.getElementById("label") ]
  }
};
var listboxNode = document.getElementById("list");
listboxNode.accessibleSource = listboxSource;
</script>
</pre>
</pre>


It's worth to notice that accessible source approach like ARIA doesn't require the author to provide comprehensive description, i.e. correlating properties may be skipped. For example, presented <code>labelledby</code> relation makes unnecessary to provide accessible name. The browser should handle this on its own.
or set it directly on the accessible element
<pre>
document.getElementById("btn").a11ement.name = "new name";
</pre>


 
or by setting its accessible source
<b>Example #3. Lazy computations.</b>
 
The previous example may look bulkier than its ARIA equivalent:


<pre>
<pre>
var listboxNode = document.getElementById("list");
document.getElementById("btn").accessibleSource = { name: "new name"; }
listboxNode.setAttribute("role", "listbox");
listboxNode.setAttribute("aria-labelledby", "label");
</pre>
</pre>


but its benefit is it allows accessible properties lazy computation. An accessible property whose value isn't changed during whole life cycle of its accessible element or which doesn't require an accessible event on its change is good candidate for lazy computation. For example the previous example may be modified this way:
These are two equivalent approaches that can be used same time and mixed with each other the way that better fits the author's intent. It's important to keep in mind though that the accessible source has a priority over ARIA attributes. Setting up the accessible source doesn't operate on DOM and thus it's supposed to be more performant as extra layer is excluded between the author and accessibility engine. Another benefit of setting the accessible source is improved code readability since the author is able to point multiple properties at once in declarative way. For example,


<pre>
<pre>
var listboxSource = {
<script>
   role: "listbox",
document.getElementById("btn").accessibleSource = {
   relations: {
   name: "new name",
    get labelledby() {
   description: "new description",
      return document.querySelectorAll("*[listboxlabel]");
   states: [ "disabled" ]
    }
   }
};
};
</script>
</pre>
</pre>


In this case the <code>labelledby</code> relation getter is more powerful than its ARIA version and all computations are running iff somebody inquired the relation.


 
====Attributes and relations====
====Patterns====


<code>
<code>
AccessibleSource .''patterns''
AccessibleSource .''attributes''
::Returns a list of all patterns implemented by the accessible element.
::A map of attribute names and their values applied to the accessible element
</code>
AccessibleSource .''relations''
 
::A map of relation types and relations for this accessible element. The bunch of types may be used to point out related elements. You can use either ''Node'', ''AccessibleElement'' or ''AccessibleSource'' objects. In latter case the object has to be in the accessible tree, in other words, it has to have associated accessible element when relation is poked by AT.
<code>
AccessibleSource .''toPattern''
::Returns an object for the given pattern. If the method is not provided then the source object has to implemented itself all claimed patterns.
</code>
</code>




<b>Example #4. Implement patterns.</b>
<b> Example #2. Adding semantics.</b>


The accessible source can be also used when the author wants to add semantics to semantically neutral element. For example, the author can turn an ordinal HTML div element into listbox control:
<pre>
<pre>
var slider = {
<label id="label">Names:</label>
  role: "slider",
<div id="list"></div>
  patterns: [ "value" ],
  toPattern: function(aName) {
    return aName == "value" ? this : null;
  },


   min: 0,
<script>
   max: 100,
var listboxSource = {
   value: 0
   role: "listbox",
   relations: {
    "labelledby": [ document.getElementById("label") ]
   }
};
};
var listboxNode = document.getElementById("list");
listboxNode.accessibleSource = listboxSource;
</script>
</pre>
</pre>


It's worth to notice that accessible source approach like ARIA doesn't require the author to provide comprehensive description, i.e. correlating properties may be skipped. For example, presented <code>labelledby</code> relation makes unnecessary to provide accessible name. The browser should handle this on its own.


====Text====


<code>
<b>Example #3. Lazy computations.</b>
AccessibleSource .''text''
::Return the text.


AccessibleSource .''textAttributesAt''
The previous example may look bulkier than its ARIA equivalent:
::Returns object of { name: value } pairs representing text attributes at given offset within the accessible element text.
</code>


<pre>
var listboxNode = document.getElementById("list");
listboxNode.setAttribute("role", "listbox");
listboxNode.setAttribute("aria-labelledby", "label");
</pre>


<b> Example #5. Text content.</b>
but its benefit is it allows accessible properties lazy computation. An accessible property whose value isn't changed during whole life cycle of its accessible element or which doesn't require an accessible event on its change is good candidate for lazy computation. For example the previous example may be modified this way:
 
While text should be normally in the content, there are cases when the author has to provide it for non-text content. For example, this technique can be used to turn HTML image into text.


<pre>
<pre>
<div id="container"></div>
var listboxSource = {
 
   role: "listbox",
<script>
   relations: {
var elm = document.getElementById("container");
     get labelledby() {
elm.innerHTML = "I " + <img src="love.png"> + "you";
       return document.querySelectorAll("*[listboxlabel]");
 
var psource = {
   role: "paragraph",
  text: "I love you",
   textAttributesAt: function(aOffset) {
     if (aOffset >= 5 && aOffset <= 7) {
       return { color: "red" }; // "love" is red
     }
     }
   }
   }
};
};
elm.accessibleSource = psource;
</script>
</pre>
</pre>


====Actions====
In this case the <code>labelledby</code> relation getter is more powerful than its ARIA version and all computations are running iff somebody inquired the relation.
 
 
====Patterns====


<code>
<code>
AccessibleSource .''actions''
AccessibleSource .''patterns''
::Return all supported actions on the accessible element.
::Returns a list of all patterns implemented by the accessible element.
</code>


AccessibleSource .''activate''
<code>
::Invoke the given action.
AccessibleSource .''toPattern''
::Parameters
::Returns an object for the given pattern. If the method is not provided then the source object has to implemented itself all claimed patterns.
:::''action''
::::the action name to invoke
</code>
</code>




<b>Example #6. Describe actions and interactions.</b>
<b>Example #4. Implement patterns.</b>


<pre>
<pre>
function listitem(aName)
var slider = {
{
   role: "slider",
   return {
  patterns: [ "value" ],
    role: "treeitem",
  toPattern: function(aName) {
    name: aName,
    return aName == "value" ? this : null;
    actions: {
  },
      select: {
 
        interactions: [ { mouse: "click" } ]
  min: 0,
      }
  max: 100,
    }
   value: 0
   };
};
};
</pre>
</pre>


In case if interactions cannot be provided then the accessible source have to implement <code>activate</code> method to invoke actions.


====Inheritance====
====Text====


<code>
<code>
AccessibleSource .''element''
AccessibleSource .''text''
::Refers to the accessible element implementation as there were no accessible source attached to it. Set by the browser when the accessible source is attached to the accessible element.
::Return the text.
 
AccessibleSource .''textAttributesAt''
::Returns object of { name: value } pairs representing text attributes at given offset within the accessible element text.
</code>
</code>




<b>Example. Lazy extension of accessible relations.</b>
<b> Example #5. Text content.</b>
 
While text should be normally in the content, there are cases when the author has to provide it for non-text content. For example, this technique can be used to turn HTML image into text.


<pre>
<pre>
var source = {
<div id="container"></div>
  get relations() {
 
    var r = this.element.relations;
<script>
    r.add("labelledby", document.querySelector(this.selector));
var elm = document.getElementById("container");
    return r;
elm.innerHTML = "I " + <img src="love.png"> + "you";
   },
 
   element: null,
var psource = {
   selector: ""
   role: "paragraph",
   text: "I love you",
   textAttributesAt: function(aOffset) {
    if (aOffset >= 5 && aOffset <= 7) {
      return { color: "red" }; // "love" is red
    }
  }
};
};
document.getElementById("button").accessibleSource = source;
elm.accessibleSource = psource;
</script>
</pre>
</pre>


===Change the accessible tree===
====Actions====


The web developer can alter existing accessible tree including subtree creations and deletions. This can be done either by <code>AccessibleSource</code> object assigned to the accessible element or by direct manipulations on the accessible tree.
<code>
AccessibleSource .''actions''
::Return all supported actions on the accessible element.


====Direct tree alteration====
AccessibleSource .''activate''
 
::Invoke the given action.
Accessible source object can be used to create new accessible element and insert it into the tree. If DOM node is used as a source then associated subtrees of accessible elements within the DOM node are reparanted, i.e. they are removed from children of its current accessible parent and added as children of new parent. Accessible element can be removed from children.
::Parameters
:::''action''
::::the action name to invoke
</code>
 
 
<b>Example #6. Describe actions and interactions.</b>


<pre>
<pre>
partial interface AccessibleChildren {
function listitem(aName)
   void append(AccessibleSource or DOMNode ... children);
{
  void insertBefore(AccessibleElement before, AccessibleSource or DOMNode ... children);
   return {
  void insertAfter(AccessibleElement after, AccessibleSource or DOMNode ... children);
    role: "treeitem",
  void replace(AccessibleSource or DOMNode ... children);
    name: aName,
  void remove(AccessibleElement ... children);
    actions: {
   void clear();
      select: {
        interactions: [ { mouse: "click" } ]
      }
    }
   };
};
};
</pre>
</pre>


<code>
In case if interactions cannot be provided then the accessible source have to implement <code>activate</code> method to invoke actions.
Children .''append''
 
::Appends accessible elements provided by sources as children to the accessible element.
====Inheritance====


Children .''insertBefore''
<code>
::Inserts accessible elements provided by sources before the given child.
AccessibleSource .''element''
 
::Refers to the accessible element implementation as there were no accessible source attached to it. Set by the browser when the accessible source is attached to the accessible element.
Children .''insertAfter''
::Inserts accessible elements provided by sources after the given child.
 
Children .''replace''
::Replaces existing children accessible elements within elements provided by sources.
 
Children .''remove''
::Removes accessible elements from the accessible tree.
 
Children .''clear''
::Removes all child accessible elements.
</code>
</code>




<b>Example</b>
<b>Example. Lazy extension of accessible relations.</b>


<pre>
<pre>
<input id="input" role="combobox">
var source = {
<div id="list" role="listbox">
  get relations() {
  <div role="listitem">choice1</div>
    var r = this.element.relations;
  <div role="listitem">choice1</div>
    r.add("labelledby", document.querySelector(this.selector));
</div>
    return r;
 
  },
<script>
  element: null,
var input = document.getElementById("input").a11ement;
  selector: ""
input.children.replace(document.getElementById("list"));
};
</script>
document.getElementById("button").accessibleSource = source;
</pre>
</pre>


===Change the accessible tree===


====Build up the tree via accessible source====
The web developer can alter existing accessible tree including subtree creations and deletions. This can be done either by <code>AccessibleSource</code> object assigned to the accessible element or by direct manipulations on the accessible tree.
 
====Direct tree alteration====


You can provide child accessible elements for the given accessible element by assigning <code>AccessibleSource</code> object to it. This approach allows to create whole portions of the accessible tree for the content having no underlying DOM nodes.
Accessible source object can be used to create new accessible element and insert it into the tree. If DOM node is used as a source then associated subtrees of accessible elements within the DOM node are reparanted, i.e. they are removed from children of its current accessible parent and added as children of new parent. Accessible element can be removed from children.


<pre>
<pre>
partial interface AccessibleSource {
partial interface AccessibleChildren {
   sequence<AccessibleSource or DOMNode> children;
  void append(AccessibleSource or DOMNode ... children);
  void insertBefore(AccessibleElement before, AccessibleSource or DOMNode ... children);
  void insertAfter(AccessibleElement after, AccessibleSource or DOMNode ... children);
   void replace(AccessibleSource or DOMNode ... children);
  void remove(AccessibleElement ... children);
  void clear();
};
};
</pre>
</pre>


<code>
<code>
AccessibleSource .''children''
Children .''append''
::Return collection of accessible children. If AccessibleSource is provided then it's used to create a new accessible element and insert it as a child. If accessible DOMNode is provided then its accessible element is used, if inaccessible DOMNode is provided then its accessible children if any are used.
::Appends accessible elements provided by sources as children to the accessible element.
 
Children .''insertBefore''
::Inserts accessible elements provided by sources before the given child.
 
Children .''insertAfter''
::Inserts accessible elements provided by sources after the given child.
 
Children .''replace''
::Replaces existing children accessible elements within elements provided by sources.
 
Children .''remove''
::Removes accessible elements from the accessible tree.
 
Children .''clear''
::Removes all child accessible elements.
</code>
</code>




<b>Example. Add list with items into the tree.</b>
<b>Example</b>


<pre>
<pre>
var tree = {
<input id="input" role="combobox">
  role: "listbox",
<div id="list" role="listbox">
   name: "colors",
   <div role="listitem">choice1</div>
   children: [
   <div role="listitem">choice1</div>
    {
</div>
      role: "listitem",
 
      states: "focusable",
<script>
      name: "red"
var input = document.getElementById("input").a11ement;
    },
input.children.replace(document.getElementById("list"));
    {
</script>
      role: "listitem",
      states: "focusable",
      name: "green"
    }
  ]
};
divNode.accessibleSource = tree;
</pre>
</pre>




====Canvas hit regions====
====Build up the tree via accessible source====


Canvas [https://html.spec.whatwg.org/multipage/scripting.html#hit-regions hit region options] are extended by ''a11ement'' which is used to connect accessible element with hit region. Whenever hit region is activated then ''activate'' method of connected ''AccessibleSource'' object is called with no argument provided.
You can provide child accessible elements for the given accessible element by assigning <code>AccessibleSource</code> object to it. This approach allows to create whole portions of the accessible tree for the content having no underlying DOM nodes.
 
Say you have a canvas with drawn button. In order to make it accessible you can create accessible button right in JS.


<pre>
<pre>
var source = {
partial interface AccessibleSource {
   role: "button",
   sequence<AccessibleSource or DOMNode> children;
  name: "test",
};
  actions: {
</pre>
    click: {
      interactions: {
        mouse: "click"
      }
    }
  },
  onactivated: function(aEvent) {
    if (aEvent.region == "button")
      this.proto.set("focused");
    else
      this.proto.states.unset("focused");
  }
  proto: null
};


canvasNode.addHitRegion({ id: "button", a11ement: source });
<code>
canvasNode.addEventListener("click", source.onactivated.bind(source));
AccessibleSource .''children''
</pre>
::Return collection of accessible children. If AccessibleSource is provided then it's used to create a new accessible element and insert it as a child. If accessible DOMNode is provided then its accessible element is used, if inaccessible DOMNode is provided then its accessible children if any are used.
</code>


===Feedback notifications===


Accessible element may be notified of any kind of event, including about property change when managed by connected source object. When notified the browser may fire accessible events and update its cache if necessary. Decision whether to notify the browser or not should be based on the accessible events model. In other words if a property change in native markup causes accessible event then it's quite likely the event is expected for similar accessible source change.
<b>Example. Add list with items into the tree.</b>


<pre>
<pre>
partial interface AccessibleElement {
var tree = {
   void notifyOf(DOMString eventType, optional Object attrs);
   role: "listbox",
  name: "colors",
  children: [
    {
      role: "listitem",
      states: "focusable",
      name: "red"
    },
    {
      role: "listitem",
      states: "focusable",
      name: "green"
    }
  ]
};
};
divNode.accessibleSource = tree;
</pre>
</pre>




<code>
====Canvas hit regions====
AccessibleElement .''notifyOf''
::Called when source has been changed to notify the host accessible element about property change. The browser is responsible to fire proper accessible events and update its internal representation.
::Parameters
:::eventType of DOMString
::::The event type to fire.
:::attrs
::::Attributes describing the event. See [[#Event_types|event types]] for attributes variety.
</code>


Canvas [https://html.spec.whatwg.org/multipage/scripting.html#hit-regions hit region options] are extended by ''a11ement'' which is used to connect accessible element with hit region. Whenever hit region is activated then ''activate'' method of connected ''AccessibleSource'' object is called with no argument provided.


If the above listbox gets disabled then you have to reflect that in its state:
Say you have a canvas with drawn button. In order to make it accessible you can create accessible button right in JS.


<pre>
<pre>
var listboxSource = {
var source = {
   role: "listbox",
   role: "button",
   name: "breed list",
   name: "test",
   states: "disabled",
   actions: {
 
    click: {
   get element() { return this.elm; }
      interactions: {
   set element(aElm) {
        mouse: "click"
     this.elm = aElm;
      }
    this.elm.notifyOf("change:name");
    }
     this.elm.notifyOf("change:states", { added: "disabled" });
   },
   onactivated: function(aEvent) {
     if (aEvent.region == "button")
      this.element.set("focused");
     else
      this.element.states.unset("focused");
   }
   }
  element: null // set by the browser
};
};


function onfocus(aEvent) {
canvasNode.addHitRegion({ id: "button", a11ement: source });
  // Change accessible properties when element is focused.
canvasNode.addEventListener("click", source.onactivated.bind(source));
  // The change requires accessible events.
  aEvent.target.accessibleSource = listboxSource;
}
</pre>
</pre>


===Implied semantics===
===Feedback notifications===


The author has to be less verbose as possible. If a role usually implies number of sets or attributes then they are supposed to set so the authur doesn't need to list them. For example if <code>listitem</code> is selectable then you don't have to point <code>selectable</code> state on it, in other words, these code snippets are equivalent:
Accessible element may be notified of any kind of event, including about property change when managed by connected source object. When notified the browser may fire accessible events and update its cache if necessary. Decision whether to notify the browser or not should be based on the accessible events model. In other words if a property change in native markup causes accessible event then it's quite likely the event is expected for similar accessible source change.


<pre>
<pre>
var source = {
partial interface AccessibleElement {
   role: "listitem"
   void notifyOf(DOMString eventType, optional Object attrs);
};
};
</pre>
</pre>


<pre>
var source = {
  role: "listitem",
  states: [ "selectable" ]
};
</pre>


The implied semantics is described by [[#SemanticsProviders|semantics provides]].
<code>
AccessibleElement .''notifyOf''
::Called when source has been changed to notify the host accessible element about property change. The browser is responsible to fire proper accessible events and update its internal representation.
::Parameters
:::eventType of DOMString
::::The event type to fire.
:::attrs
::::Attributes describing the event. See [[#Event_types|event types]] for attributes variety.
</code>


===Conflicts===


[to be done conflicts between native semantics, ARIA and this API]
If the above listbox gets disabled then you have to reflect that in its state:
 
===Sniffing===
 
In order to make optimization the content provider has to know whether accessibility consumer is active. The provider can add a callback for <code>deploy</code> and <code>conceal</code> event types which will be triggered when consumer appears/gets inactive.


<pre>
<pre>
function deployA11y() {
var listboxSource = {
   // build accessible tree or update existing one
  role: "listbox",
   // keep the tree updated
  name: "breed list",
}
  states: "disabled",
function stopA11y() {
 
   // stop keeping the accessible tree updated
  get element() { return this.elm; }
   set element(aElm) {
    this.elm = aElm;
    this.elm.notifyOf("change:name");
    this.elm.notifyOf("change:states", { added: "disabled" });
   }
};
 
function onfocus(aEvent) {
   // Change accessible properties when element is focused.
  // The change requires accessible events.
  aEvent.target.accessibleSource = listboxSource;
}
}
document.a11ement.on("deploy", deployA11y);
document.a11ement.on("conceal", stopA11y);
</pre>
</pre>


<div id="SemanticsProviders">
===Implied semantics===


==Semantics providers==
The idea is to help the author to keep the code less verbose as possible. If role implies a number of preset attributes or states then they are present on the accessible element by default, i.e. if the author didn't list them. For example, if <code>listitem</code> role is selectable and focusable by default then the author doesn't have to point <code>selectable</code> and <code>focusable</code> states when he describes a listitem source, in other words, these code snippets are equivalent:
</div>
 
The author of the content which is not a standard HTML has to provide content semantics to make the content accessible. In other words, he has to describe a semantic vocabulary that will be used to give the content specific meaning. For example, if you are ebook publisher then you will need a bunch of new roles like 'bibliography' or 'appendix'. If you do operate with complex widgets then likely you will need to describe its states, attributes or relations.


<pre>
<pre>
partial interface AccessibleDocument {
var source1 = {
   void import(DOMString name, Object taxonomy);
   role: "listitem"
};
 
var source2 = {
  role: "listitem",
  states: [ "selectable", "focusable" ]
};
};
</pre>
</pre>


<code>
Implied semantics is described by [[#SemanticsProviders|taxonomies]].
AccessibleDocument .''import''
 
::Import the taxonomy.
 
::Parameters
===Conflicts===
:::name of DOMString
 
::::taxonomy name like ''role'' or ''states''
[to be done conflicts between native semantics, ARIA and this API, I tend to think that the author should be able to replace/remove native semantics if needed. This can ruin the web page but it gives the absolute control over the page content. A dangerous but quite powerful tool like atomic energy. ]
:::taxonomy of Object
 
::::a collection of taxa and their properties.
::Throws
:::if there's names conflict or there are invalid relations between taxonomies then an exception should be thrown [todo].
</code>


===Sniffing===


Depending on [[#TaxonomyTypes|taxonomy type]], a taxa may be described by specific fields and be connected with other taxonomies. For example, DPUB semantics may be described this way:
In order to make an optimization, the content provider has to know whether an accessibility consumer (like screen reader) is active. The provider can add a callback for <code>deploy</code> and <code>conceal</code> event types which will be triggered when consumer appears/gets inactive.  


<pre>
<pre>
document.accessibleElement.import("role",
function deployA11y() {
{
   // build accessible tree or update existing one
   appendix: {
   // keep the tree updated
    parents: "section",
}
    landmark: "appendix",
function stopA11y() {
    description: "appendix"
   // stop keeping the accessible tree updated
  },
   bibliography: {
    parents: "list",
    landmark: "bibliography",
    owns: "biblioentry",
    description: "bibliography"
  },
  biblioentry: {
    parents: "listitem",
    description: "reference"
   }
}
}
document.a11ement.on("deploy", deployA11y);
document.a11ement.on("conceal", stopA11y);
</pre>
</pre>


This approach is alternative to [https://w3c.github.io/aria/aria/dpub.html DPUB ARIA extensions]. Any web app operating with DPUB content can import JS file describing the taxonomies and the browser can expose the content properly to the assistive technology. No special support on the browser side is required.
<div id="SemanticsProviders">


==Semantics providers==
</div>


In short reasons to provide taxonomy are:
The author of the content which is not a standard HTML has to provide content semantics to make the content accessible. In other words, he has to describe a semantic vocabulary that will be used to give the content specific meaning. For example, if you are ebook publisher then you will need a bunch of new roles like 'bibliography' or 'appendix'. If you do operate with complex widgets then likely you will need to describe its states, attributes or relations.
* The browser automatically maps the content to desktop accessibility APIs;
* The web accessibility technology knows how to expose the content;
* Adds implied accessibility support for the content;
* Automatic content validation.


 
<pre>
<div id="Taxonomy">
===Taxonomies===
</div>
 
You can get hierarchical relations between roles, states, actions or anything else that has a taxonomy. For example, if the web author introduces a role 'checklistitem' which is compound from two roles 'checkbox' and 'listitem', i.e it inherits properties of both of them then the web author should integrate the new role into existing role hierarchy. Taxonomies are scoped by <code>AccessibleDocument</code> which provides bunch of methods to get them.
 
<pre>
partial interface AccessibleDocument {
partial interface AccessibleDocument {
   Taxon? taxonOf(in DOMString taxonomy, in DOMString name);
   void import(DOMString name, Object taxonomy);
  Taxonomy? taxonomyOf(DOMString name);
};
};
</pre>
</pre>


<code>
<code>
AccessibleDocument .''taxonOf''
AccessibleDocument .''import''
::Returns a taxon for the given taxon name of requested taxonomy.
::Import the taxonomy.
::Parameters
::Parameters
:::taxonomy
:::name of DOMString
::::a taxonomy name
::::taxonomy name like ''role'' or ''states''
:::name
:::taxonomy of Object
::::name of requested taxa like 'button' in case of 'role' taxonomy
::::a collection of taxa and their properties.
</code>
::Throws
 
:::if there's names conflict or there are invalid relations between taxonomies then an exception should be thrown [todo].
<code>
AccessibleDocument .''taxonomyOf''
::Return an object describing requested taxonomy.
::Parameters
:::name
::::a taxonomy name
</code>
</code>


Depending on [[#TaxonomyTypes|taxonomy type]], a taxa may be described by specific fields and be connected with other taxonomies. For example, DPUB semantics may be described this way:


<pre>
<pre>
interface Taxon {
document.accessibleElement.import("role",
   stringifier readonly attribute DOMString name;
{
   readonly attribute DOMString description;
  appendix: {
    parents: "section",
    landmark: "appendix",
    description: "appendix"
   },
   bibliography: {
    parents: "list",
    landmark: "bibliography",
    owns: "biblioentry",
    description: "bibliography"
  },
  biblioentry: {
    parents: "listitem",
    description: "reference"
  }
}
</pre>
 
This approach is alternative to [https://w3c.github.io/aria/aria/dpub.html DPUB ARIA extensions]. Any web app operating with DPUB content can import JS file describing the taxonomies and the browser can expose the content properly to the assistive technology. No special support on the browser side is required.


  readonly attribute sequence<Taxon> parentTaxa;
  readonly attribute sequence<Taxon> childTaxa;


  bool is(DOMString or Taxon base);
In short reasons to provide taxonomy are:
* The browser automatically maps the content to desktop accessibility APIs;
* The web accessibility technology knows how to expose the content;
* Adds implied accessibility support for the content;
* Automatic content validation.


  readonly attribute AttributeMap attributes;
  readonly attribute RelationMap relations;
};
</pre>


<code>
<div id="Taxonomy">
Taxon .''name''
===Taxonomies===
::Return name of the taxa
</div>


Taxon .''description''
You can get hierarchical relations between roles, states, actions or anything else that has a taxonomy. For example, if the web author introduces a role 'checklistitem' which is compound from two roles 'checkbox' and 'listitem', i.e it inherits properties of both of them then the web author should integrate the new role into existing role hierarchy. Taxonomies are scoped by <code>AccessibleDocument</code> which provides bunch of methods to get them.
::Return localized description of the taxa
</code>


<pre>
partial interface AccessibleDocument {
  Taxon? taxonOf(in DOMString taxonomy, in DOMString name);
  Taxonomy? taxonomyOf(DOMString name);
};
</pre>


<code>
<code>
Taxon .''parentTaxa''
AccessibleDocument .''taxonOf''
::Return list of taxa the taxon is inherited from.
::Returns a taxon for the given taxon name of requested taxonomy.
 
::Parameters
Taxon .''childTaxa''
:::taxonomy
::Return list of taxa that is inherited from this taxon.
::::a taxonomy name
 
:::name
Taxon .''is''
::::name of requested taxa like 'button' in case of 'role' taxonomy
::Return true if given taxon name is in base of the taxon.
</code>
</code>


<code>
<code>
Taxon .''attributes''
AccessibleDocument .''taxonomyOf''
::Return a map between attribute names and attribute values specific for the taxon.
::Return an object describing requested taxonomy.
 
::Parameters
Taxon .''relations''
:::name
::Return a map between relation types and related taxa specific for the taxon.
::::a taxonomy name
</code>
</code>




<b>Example #1. Handle new role as it was known.</b>
<pre>
<pre>
var taxa = {
interface Taxon {
   checklistitem: {
   stringifier readonly attribute DOMString name;
    parents: [ "checkbox", "menuitem" ]
   readonly attribute DOMString description;
   }
};
document.accessibleElement.import("role", taxa);
</pre>


<pre>
  readonly attribute sequence<Taxon> parentTaxa;
var taxon = document.accessibleElement.taxonOf("role", "checklistitem");
   readonly attribute sequence<Taxon> childTaxa;
if (taxon.is("menuitem")) {
   // process menuitem selection
}
</pre>


<b>Example #2. Checking whether role is a navigational landmark.</b>
  bool is(DOMString or Taxon base);


<pre>
  readonly attribute AttributeMap attributes;
var taxon = document.accessibleDocument.taxonOf("role", "main");
  readonly attribute RelationMap relations;
var isLandmark = taxon.attributes.has("landmark");
};
</pre>
</pre>


<b>Example #3. Getting states specific to the role.</b>
<code>
Taxon .''name''
::Return name of the taxa


<pre>
Taxon .''description''
var taxon = document.accessibleDocument.taxonOf("role", "listbox");
::Return localized description of the taxa
print(listboxRole.relations.get("states"))); // prints "focusable"
</code>
</pre>




====Managing the taxonomies====
<code>
Taxon .''parentTaxa''
::Return list of taxa the taxon is inherited from.


<pre>
Taxon .''childTaxa''
interface Taxonomy {
::Return list of taxa that is inherited from this taxon.
  Taxon? taxonOf(DOMString name);
  readonly attribute sequence<Taxon> rootTaxa;


  void addTaxon(DOMString name, sequence<Taxon or DOMString> baseTaxa);
Taxon .''is''
  void removeTaxon(Taxon taxon);
::Return true if given taxon name is in base of the taxon.
};
</pre>
 
<code>
Taxonomy .''getTaxon''
::Return a taxon object for the given name.
::Parameters
:::name
::::taxon name
</code>
</code>


<code>
Taxonomy .''rootTaxa''
::Return list of base taxa
</code>


<code>
<code>
Taxonomy .''addTaxon''
Taxon .''attributes''
::Adds new taxon into the taxonomy.
::Return a map between attribute names and attribute values specific for the taxon.
::Parameters
:::name
::::a new taxon name
:::baseTaxa
::::a list of taxa the taxon is inherited from
</code>


<code>
Taxon .''relations''
Taxonomy .''removeTaxon''
::Return a map between relation types and related taxa specific for the taxon.
::Remove the given taxon and all taxa inherited from it from the taxonomy.
::Parameters
:::taxon
::::taxon object
</code>
</code>




<div id="TaxonomyTypes">
<b>Example #1. Handle new role as it was known.</b>
===Taxonomy types===
</div>
 
====Roles====
 
<pre>
<pre>
dictionary RoleTaxa {
var taxa = {
   DOMString landmark;
   checklistitem: {
  DOMString description;
    parents: [ "checkbox", "menuitem" ]
 
   }
  DOMString or sequence<DOMString> parents;
  DOMString or sequence<DOMString> owns;
  DOMString or sequence<DOMString> states;
   Object attributes;
};
};
document.a11ement.import("role", taxa);
</pre>
</pre>


<pre>
var taxon = document.a11ement.taxonOf("role", "checklistitem");
if (taxon.is("menuitem")) {
  // process menuitem selection
}
</pre>


<code>
<b>Example #2. Checking whether role is a navigational landmark.</b>
RoleTaxa .''landmark''
::Navigation landmark name if applicable.


RoleTaxa .''description''
<pre>
::Localized role description.
var taxon = document.a11ement.taxonOf("role", "main");
var isLandmark = taxon.attributes.has("landmark");
</pre>


RoleTaxa .''parents''
<b>Example #3. Getting states specific to the role.</b>
::List of roles the role is inherited from.


RoleTaxa .''owns''
<pre>
::List of roles allowed in children of the role. Used for validation.
var taxon = document.a11ement.taxonOf("role", "listbox");
print(listboxRole.relations.get("states"))); // prints "focusable"
</pre>


RoleTaxa .''states''
::List of states allowed on the role.


RoleTaxa .''attributes''
====Managing the taxonomies====
::List of attributes maintained by the role.
</code>
 
====States====


<pre>
<pre>
dictionary StateTaxa {
interface Taxonomy {
}
  Taxon? taxonOf(DOMString name);
</pre>
  readonly attribute sequence<Taxon> rootTaxa;
 
  void addTaxon(DOMString name, sequence<Taxon or DOMString> baseTaxa);
  void removeTaxon(Taxon taxon);
};
</pre>
 
<code>
Taxonomy .''getTaxon''
::Return a taxon object for the given name.
::Parameters
:::name
::::taxon name
</code>
 
<code>
Taxonomy .''rootTaxa''
::Return list of base taxa
</code>
 
<code>
Taxonomy .''addTaxon''
::Adds new taxon into the taxonomy.
::Parameters
:::name
::::a new taxon name
:::baseTaxa
::::a list of taxa the taxon is inherited from
</code>
 
<code>
Taxonomy .''removeTaxon''
::Remove the given taxon and all taxa inherited from it from the taxonomy.
::Parameters
:::taxon
::::taxon object
</code>
 
 
<div id="TaxonomyTypes">
 
===Taxonomy types===
</div>
 
Each taxonomy is described means of its own interface which is used to define the hierarchy and interconnections between taxonomies. If taxon refers to taxa of other taxonomy type then a string describing the reference may be in form of "taxon:modifier", where taxon is a name of related taxon and modifier is an extra information about how the taxa are interconnected. For example, role taxon may be connected to "live" taxon of attributes taxonomy by placing "live:assertive" value in <code>attributes</code> field which means that the role supports "live" object attribute and its default value is "assertive" on it.
 
====Roles====
 
<pre>
dictionary RoleTaxon {
  DOMString landmark;
  DOMString description;
 
  sequence<DOMString> parents;
  sequence<DOMString> owns;
  sequence<DOMString> states;
  Object attributes;
  sequence<DOMString> relations;
  sequence<DOMString> actions;
};
</pre>
 
 
<code>
RoleTaxon .''landmark''
::Navigation landmark name if applicable.
 
RoleTaxon .''description''
::Localized role description.
 
RoleTaxon .''parents''
::List of roles the role is inherited from.
 
RoleTaxon .''owns''
::List of roles allowed in children of the role. Used for validation.
 
RoleTaxon .''states''
::List of states allowed on the role. Optional modifier is "default" which points out that the state is exposed on the role until explicitly specified otherwise. See [[#Implied_semantics|implied semantics]].
 
RoleTaxon .''attributes''
::List of attributes supported by the role. Default value of the attribute may be specified as modifier. For example, "live:polite" points out that "live" object attribute has "polite" value by default. If default value is not specified then it's taken from referred attribute taxon description.
 
RoleTaxon .''relations''
::List of relations supported by the role.
 
RoleTaxon ..''actions''
::List of supported actions. Actions from the list are exposed on the accessible element depending on states present on it. For example, if supported actions are "check" and "uncheck", then "check" is exposed if the accessible element doesn't have "checked" state, otherwise "unchecked".
</code>
 
 
<b>Example. ARIA <code>textbox</code> role.</b>
 
<pre>
var taxa = {
  widget: { }
  input: {
    parents: [ "widget" ],
    states: [ "focusable:default", "focused" ]
  },
  textbox: {
    description: "text field",
    parents: [ "input" ],
    states: [
      "singleline:default", "multiline",
      "editable", "readonly",
      "required"
    ],
    attributes: [ "autocomplete" ]
  }
};
</pre>
 
 
<b>Example. ARIA <code>checkbox</code> role.</b>
 
<pre>
var taxa = {
  checkbox: {
    description: "checkbox",
    parents: [ "input" ],
    states: [ "checkable:default, "checked" ],
    actions: [ "check", "uncheck" ]
  }
};
</pre>
 
 
<b>Example. ARIA <code>log</code> role.</b>
 
<pre>
var taxa = {
  region: {
  },
  log: {
    parents: [ "region" ],
    attributes: [ "live:polite" ]
  }
};
</pre>
 
====States====
 
<pre>
dictionary StateTaxon {
  DOMString description;
  sequence<DOMString> dependents;
  DOMString exclusives;
}
</pre>
 
 
<code>
StateTaxon .''description''
::Localized taxa description.
 
StateTaxon .''dependents''
::List of all dependent states. For example, "focused" state always accompanied by "focusable" state.
 
StateTaxon ..''exclusives''
::Mutually exclusive states if applicable. For example, if "vertical" state is applied then "horizontal" is not and vice versa.
</code>
 
 
<b>Example.</b>
 
<pre>
var taxa = {
  focusable: {
    dependents: [ "focused" ]
  },
  focused: { },
 
  singleline: {
    exlcusives: [ "multiline" ]
  },
  multiline: {
    exlcusives: [ "singleline" ]
  },
 
  readonly: { },
  editable: { },
  required: { },
 
  checked: {
    exlusives: [ "mixed" ]
  },
  mixed: {
    exlusives: [ "checked" ]
  }
};
</pre>
 
====Attributes====
 
<pre>
interface AttributeTaxon {
  DOMString description;
  sequence<DOMString> values;
  DOMString default;
};
</pre>
 
 
<code>
AttributeTaxon .''description''
::Localized description of the taxon
 
AttributeTaxon .''values''
::List of all possible values of the attrbiute
 
AttributeTaxon .''default''
::Default attribute value. Takes a place if role taxa pointing to it doesn't have own default value of it.
</code>
 
 
<b>Example</b>
 
<pre>
var taxa = {
  autocomplete: {
    values: [ "none", "list", "inline", "both" ],
    default: "none"
  },
  live: {
    values: [ "none", "polite", "assertive" ],
    default: "none"
  }
};
</pre>
 
 
====Actions====
 
<pre>
dictionary ActionTaxon {
  DOMString description;
  DOMString dual;
  sequence<DOMString> states;
};
</pre>
 
<code>
ActionTaxon .''description''
::Localized action description.
 
ActionTaxon .''dual''
::Dual action taxon. When action is invoked, it is switched to its dual action if applicable.
 
ActionTaxon .''states''
::Implied states. When action is invoked, states of dual action are cleared, this action states are set.
</code>
 
 
<b>Example.</b>
 
<pre>
var taxa = {
  check: {
    description: "check",
    dual: "uncheck",
    states: [ "checked" ]
  },
  uncheck: {
    description: "uncheck",
    dual: "check"
  }
};
</pre>
 
=HTML and beyond=
 
This doc introduces common patterns to express the semantics of markup languages to accessibility. Markup specifics is not a target for this doc in general. Each markup specification has to take care to describe their accessibility stuff in terms of this API.
 
=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:
 
<pre>
roles:
  'sheet' - inherited from 'section'
  'note' - inherited from 'image', describes the note
</pre>
 
<pre>
role 'sheet' attributes:
  instrument: DOMString,
  tempo: number/DOMString
  clef: DOMString
</pre>
 
<pre>
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
</pre>
 
<pre>
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
</pre>
 
 
Or in terms of taxonomies:
 
<pre>
document.import("role", {
  sheet: {
    description: "sheet",
    attributes: [ "instrument", "tempo", "clef" ]
  },
  note: {
    description: "note",
    attributes: [ "key", "alteration", "octave", "duration", "effects" ],
    relations: [ "crescendo", "diminuendo" ]
  }
});


=HTML and beyond=
document.import("attributes", {
  instrument: {
    description: "instrument type"
  },
  tempo: {
    description: "tempo"
  },
  clef: {
    description: "clef"
  },
  key: {
    description: "key",
    values: [ "C", "D", "E", "F", "G", "A", "H" ],
  },
  alteration: {
    description: "alteration",
    values: [ "none", "flat", "sharp" ],
    default: "none"
  },
  octave: {
    description: "octave",
    values: [ "contra", "great", "small", "1line", "2line" ],
  },
  duration: {
    description: "duration"
  },
  effects: {
    description: "effects"
  }
});


This doc introduces common patterns to express the semantics of markup languages to accessibility. Markup specifics is not a target for this doc in general. Each markup specification has to take care to describe their accessibility stuff in terms of this API.
document.import("relations", {
 
   crescendo: {
=Extensibility=
    description: "crescendo"
 
   },
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.
   diminuendo: {
 
    description: "diminuendo"
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:
 
<pre>
roles:
  'sheet' - inherited from 'section'
  'note' - inherited from 'image', describes the note
</pre>
 
<pre>
role 'sheet' attributes:
   instrument: DOMString,
  tempo: number/DOMString
   clef: DOMString
</pre>
 
<pre>
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
</pre>
 
<pre>
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
</pre>
</pre>
Confirmed users
1,396

edits