]>
git.wh0rd.org - tt-rss.git/blob - lib/dijit/a11y.js.uncompressed.js
2 "dojo/_base/array", // array.forEach array.map
3 "dojo/_base/config", // defaultDuration
4 "dojo/_base/declare", // declare
5 "dojo/dom", // dom.byId
6 "dojo/dom-attr", // domAttr.attr domAttr.has
7 "dojo/dom-style", // style.style
8 "dojo/_base/sniff", // has("ie")
9 "./_base/manager", // manager._isElementShown
10 "." // for exporting methods to dijit namespace
11 ], function(array
, config
, declare
, dom
, domAttr
, domStyle
, has
, manager
, dijit
){
16 // Accessibility utility functions (keyboard, tab stops, etc.)
18 var shown
= (dijit
._isElementShown = function(/*Element*/ elem
){
19 var s
= domStyle
.get(elem
);
20 return (s
.visibility
!= "hidden")
21 && (s
.visibility
!= "collapsed")
22 && (s
.display
!= "none")
23 && (domAttr
.get(elem
, "type") != "hidden");
26 dijit
.hasDefaultTabStop = function(/*Element*/ elem
){
28 // Tests if element is tab-navigable even without an explicit tabIndex setting
30 // No explicit tabIndex setting, need to investigate node type
31 switch(elem
.nodeName
.toLowerCase()){
33 // An <a> w/out a tabindex is only navigable if it has an href
34 return domAttr
.has(elem
, "href");
41 // These are navigable by default
44 // If it's an editor <iframe> then it's tab navigable.
48 var contentDocument
= elem
.contentDocument
;
49 if("designMode" in contentDocument
&& contentDocument
.designMode
== "on"){
52 body
= contentDocument
.body
;
54 // contentWindow.document isn't accessible within IE7/8
55 // if the iframe.src points to a foreign url and this
56 // page contains an element, that could get focus
58 body
= elem
.contentWindow
.document
.body
;
63 return body
&& (body
.contentEditable
== 'true' ||
64 (body
.firstChild
&& body
.firstChild
.contentEditable
== 'true'));
66 return elem
.contentEditable
== 'true';
70 var isTabNavigable
= (dijit
.isTabNavigable = function(/*Element*/ elem
){
72 // Tests if an element is tab-navigable
74 // TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable()
75 if(domAttr
.get(elem
, "disabled")){
77 }else if(domAttr
.has(elem
, "tabIndex")){
78 // Explicit tab index setting
79 return domAttr
.get(elem
, "tabIndex") >= 0; // boolean
81 // No explicit tabIndex setting, so depends on node type
82 return dijit
.hasDefaultTabStop(elem
);
86 dijit
._getTabNavigable = function(/*DOMNode*/ root
){
88 // Finds descendants of the specified root node.
91 // Finds the following descendants of the specified root node:
92 // * the first tab-navigable element in document order
93 // without a tabIndex or with tabIndex="0"
94 // * the last tab-navigable element in document order
95 // without a tabIndex or with tabIndex="0"
96 // * the first element in document order with the lowest
97 // positive tabIndex value
98 // * the last element in document order with the highest
99 // positive tabIndex value
100 var first
, last
, lowest
, lowestTabindex
, highest
, highestTabindex
, radioSelected
= {};
102 function radioName(node
){
103 // If this element is part of a radio button group, return the name for that group.
104 return node
&& node
.tagName
.toLowerCase() == "input" &&
105 node
.type
&& node
.type
.toLowerCase() == "radio" &&
106 node
.name
&& node
.name
.toLowerCase();
109 var walkTree = function(/*DOMNode*/parent
){
110 for(var child
= parent
.firstChild
; child
; child
= child
.nextSibling
){
111 // Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
112 // since show() invokes getAttribute("type"), which crash on VML nodes in IE.
113 if(child
.nodeType
!= 1 || (has("ie") && child
.scopeName
!== "HTML") || !shown(child
)){
117 if(isTabNavigable(child
)){
118 var tabindex
= domAttr
.get(child
, "tabIndex");
119 if(!domAttr
.has(child
, "tabIndex") || tabindex
== 0){
124 }else if(tabindex
> 0){
125 if(!lowest
|| tabindex
< lowestTabindex
){
126 lowestTabindex
= tabindex
;
129 if(!highest
|| tabindex
>= highestTabindex
){
130 highestTabindex
= tabindex
;
134 var rn
= radioName(child
);
135 if(domAttr
.get(child
, "checked") && rn
){
136 radioSelected
[rn
] = child
;
139 if(child
.nodeName
.toUpperCase() != 'SELECT'){
148 // substitute checked radio button for unchecked one, if there is a checked one with the same name.
149 return radioSelected
[radioName(node
)] || node
;
152 return { first
: rs(first
), last
: rs(last
), lowest
: rs(lowest
), highest
: rs(highest
) };
154 dijit
.getFirstInTabbingOrder = function(/*String|DOMNode*/ root
){
156 // Finds the descendant of the specified root node
157 // that is first in the tabbing order
158 var elems
= dijit
._getTabNavigable(dom
.byId(root
));
159 return elems
.lowest
? elems
.lowest
: elems
.first
; // DomNode
162 dijit
.getLastInTabbingOrder = function(/*String|DOMNode*/ root
){
164 // Finds the descendant of the specified root node
165 // that is last in the tabbing order
166 var elems
= dijit
._getTabNavigable(dom
.byId(root
));
167 return elems
.last
? elems
.last
: elems
.highest
; // DomNode
171 hasDefaultTabStop
: dijit
.hasDefaultTabStop
,
172 isTabNavigable
: dijit
.isTabNavigable
,
173 _getTabNavigable
: dijit
._getTabNavigable
,
174 getFirstInTabbingOrder
: dijit
.getFirstInTabbingOrder
,
175 getLastInTabbingOrder
: dijit
.getLastInTabbingOrder