diff options
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.js | 158 |
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); + } +}; |