summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/conformance-checkers/html-aria/_functional/tree/js/aria.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/conformance-checkers/html-aria/_functional/tree/js/aria.js')
-rw-r--r--testing/web-platform/tests/conformance-checkers/html-aria/_functional/tree/js/aria.js158
1 files changed, 158 insertions, 0 deletions
diff --git a/testing/web-platform/tests/conformance-checkers/html-aria/_functional/tree/js/aria.js b/testing/web-platform/tests/conformance-checkers/html-aria/_functional/tree/js/aria.js
new file mode 100644
index 0000000000..bf3bc5399e
--- /dev/null
+++ b/testing/web-platform/tests/conformance-checkers/html-aria/_functional/tree/js/aria.js
@@ -0,0 +1,158 @@
+
+/* Aria Singleton */
+var Aria = {
+ Trees: new Array(), // instances of Aria.Tree Class
+ isEnabled: function(inNode){
+ // todo: this may need to check isEnabled on all parentNodes, inheritence of aria-enabled is ambiguous
+ if(inNode.getAttribute('aria-enabled') && inNode.getAttribute('aria-enabled').toLowerCase()=='false') return false;
+ else return true;
+ },
+ isExpanded: function(inNode){
+ if(inNode.getAttribute('aria-expanded') && inNode.getAttribute('aria-expanded').toLowerCase()=='false') return false;
+ else return true;
+ },
+ isTreeItem: function(inNode){
+ if(inNode.getAttribute('role') && inNode.getAttribute('role').toLowerCase()=='treeitem') return true;
+ else return false;
+ }
+};
+
+Aria.Tree = Class.create();
+Aria.Tree.prototype = {
+ initialize: function(inNode){
+ this.el = $(inNode);
+ this.index = Aria.Trees.length; // each tree should know its index in the Aria singleton's list, in order to concatenate id strings
+ this.strActiveDescendant = this.el.getAttribute('aria-activedescendant');
+ this.strDefaultActiveDescendant = 'tree'+this.index+'_item0'; // default first item
+ if(!$(this.strActiveDescendant)) this.strActiveDescendant = this.strDefaultActiveDescendant; // set to default if no existing activedescendant
+ this.setActiveDescendant($(this.strActiveDescendant));
+
+ // set up event delegation on the tree node
+ Event.observe(this.el, 'click', this.handleClick.bindAsEventListener(this));
+ Event.observe(this.el, 'keydown', this.handleKeyPress.bindAsEventListener(this)); //webkit doesn't send keypress events for arrow keys, so use keydown instead
+
+ },
+ getActiveDescendant: function(inNode){
+ if(inNode){ // if inNode (from event target), sets the activedescendant to nearest ancestor treeitem
+ var el = $(inNode);
+ while(el != this.el){
+ if(Aria.isTreeItem(el)) break; // exit the loop; we have the treeitem
+ el = el.parentNode;
+ }
+ if(el == this.el) {
+ this.setActiveDescendant(); // set to default activedescendant
+ } else {
+ this.setActiveDescendant(el);
+ return el;
+ }
+ } else {
+ return $(this.el.getAttribute('aria-activedescendant'));
+ }
+ },
+ getNextTreeItem: function(inNode){
+ var el = $(inNode);
+ var originalElm = $(inNode);
+ while(!Aria.isTreeItem(el) || el == originalElm){
+ if(Aria.isExpanded(el) && el.down()){ // should be el.down('[role="treeitem"]');
+ var elements = el.getElementsByTagName('*');
+ for(var i=0, c=elements.length; i<c; i++){
+ if(Aria.isTreeItem(elements[i])) return elements[i];
+ }
+ }
+ if(el.next()){
+ el = el.next();
+ } else {
+ while(!el.parentNode.next() && el.parentNode != this.el){
+ el = el.parentNode;
+ }
+ if(el.parentNode == this.el) return originalElm; // if no next items in tree, return current treeitem
+ else el = el.parentNode.next();
+ }
+ }
+ return el;
+ },
+ getPreviousTreeItem: function(inNode){
+ var el = $(inNode);
+ var originalElm = $(inNode);
+ while(!Aria.isTreeItem(el) || el == originalElm){
+ if(el.previous()){
+ el = el.previous();
+ // recursively choose last child node of previous el, as long as it's not in an collapsed node
+ if (el.down() && Aria.isExpanded(el)){
+ el = el.down();
+ while (el.next() || (el.down() && Aria.isExpanded(el))){
+ if (el.next()) el = el.next();
+ else el = el.down();
+ }
+ }
+ } else {
+ if(el.parentNode == this.el) return originalElm; // if no previous items in tree, return current treeitem
+ el = el.parentNode;
+ }
+ }
+ if(el == this.el) return originalElm; // if no previous items in tree, return current treeitem
+ return el;
+ },
+ handleClick: function(inEvent){
+ var target = inEvent.target; // get the click target
+ var el = this.getActiveDescendant(target);
+ if(target.className.indexOf('expander')>-1){ // if it's an expander widget
+ this.toggleExpanded(el); // toggle the aria-expanded attribute on activedescendant
+ Event.stop(inEvent); // and stop the event
+ }
+ },
+ handleKeyPress: function(inEvent){
+ switch(inEvent.keyCode){
+ // case Event.KEY_PAGEUP: break;
+ // case Event.KEY_PAGEDOWN: break;
+ // case Event.KEY_END: break;
+ // case Event.KEY_HOME: break;
+ case Event.KEY_LEFT: this.keyLeft(); break;
+ case Event.KEY_UP: this.keyUp(); break;
+ case Event.KEY_RIGHT: this.keyRight(); break;
+ case Event.KEY_DOWN: this.keyDown(); break;
+ default:
+ return;
+ }
+ Event.stop(inEvent);
+ },
+ keyLeft: function(){
+ var el = this.activeDescendant;
+ if(Aria.isExpanded(el)){
+ el.setAttribute('aria-expanded','false');
+ this.setActiveDescendant(this.activeDescendant);
+ }
+ },
+ keyUp: function(){
+ var el = this.activeDescendant;
+ this.setActiveDescendant(this.getPreviousTreeItem(el));
+ },
+ keyRight: function(){
+ var el = this.activeDescendant;
+ if(!Aria.isExpanded(el)){
+ el.setAttribute('aria-expanded','true');
+ this.setActiveDescendant(this.activeDescendant);
+ }
+ },
+ keyDown: function(){
+ var el = this.activeDescendant;
+ this.setActiveDescendant(this.getNextTreeItem(el));
+ },
+ setActiveDescendant: function(inNode){
+ Element.removeClassName(this.activeDescendant,'activedescendant')
+ if($(inNode)) this.activeDescendant = $(inNode);
+ else this.activeDescendant = $(this.strDefaultActiveDescendant);
+ Element.addClassName(this.activeDescendant,'activedescendant')
+ this.strActiveDescendant = this.activeDescendant.id;
+ this.el.setAttribute('aria-activedescendant', this.activeDescendant.id);
+ },
+ toggleExpanded: function(inNode){
+ var el = $(inNode);
+ if(Aria.isExpanded(el)){
+ el.setAttribute('aria-expanded','false');
+ } else {
+ el.setAttribute('aria-expanded','true');
+ }
+ this.setActiveDescendant(el);
+ }
+};