blob: 428045b33abacc2257b7fea1c8e9f14d5de7625f [file] [log] [blame]
/* Aria Singleton */
var Aria = {
ManagedWidgets: new Array() // instances of Aria.ManagedWidget Class
};
Aria.ManagedWidget = Class.create();
Aria.ManagedWidget.prototype = {
initialize: function(inNode, inRole, inChildSelector, inChildRole, inAttributes, inFunctionOnSelect){
if(!$(inNode) && console.error) console.error('Error from aria.js: Aria.ManagedWidget instance initialized with invalid element, '+ inNode);
this.el = $(inNode);
this.role = inRole;
this.childSelector = inChildSelector;
this.childRole = inChildRole;
this.attributes = inAttributes;
this.selectFunction = inFunctionOnSelect;
this.index = Aria.ManagedWidgets.length; // each ManagedWidget can know its index in the Aria singleton's instance array
this.el.setAttribute('role', this.role); // set container role (e.g. radiogroup) on the el
this.childItems = this.el.select(this.childSelector);
for (var i=0, c=this.childItems.length; i<c; i++) {
var item = this.childItems[i]; // sets the child role (e.g. radio) on each child
//item.setAttribute('title', item.innerHTML.stripTags()); // set @title for mouse hover tooltip
item.setAttribute('role', this.childRole);
item.setAttribute('tabindex','-1'); // make rest of the items non-focusable
}
this.setSelectedItem(false, true); // make the first item selected, but don't focus it
// set up event delegation on the parent node instead of tracking events on all the childItems
Event.observe(this.el, 'click', this.handleClick.bindAsEventListener(this));
Event.observe(this.el, 'keydown', this.handleKeyPress.bindAsEventListener(this)); // keypress events inconsistent for arrow keys, so use keydown instead
},
getNextItem: function(inNode) {
var el = $(inNode);
if(el.next()) el = el.next(); // todo: fix this so the items don't have to be DOM siblings
return el;
},
getPreviousItem: function(inNode) {
var el = $(inNode);
if(el.previous()) el = el.previous(); // todo: fix this so the items don't have to be DOM siblings
return el;
},
getSelectedItem: function(inNode){
if(inNode){ // if inNode (from event target), sets the active item to nearest ancestor item
var el = $(inNode);
while (el != this.el) {
if (this.isChildItem(el)) break; // exit the loop; we have the item
el = el.parentNode;
}
if (el != this.el) {
return this.setSelectedItem(el);
}
}
return this.setSelectedItem(); // set to default
},
handleClick: function(inEvent) {
var target = inEvent.target; // get the click target
var el = this.getSelectedItem(target);
this.setSelectedItem(el);
Event.stop(inEvent); // and stop the event
},
handleKeyPress: function(inEvent) {
switch (inEvent.keyCode) {
case Event.KEY_DOWN: this.keyDown(); break;
case Event.KEY_LEFT: this.keyLeft(); break;
case Event.KEY_RIGHT: this.keyRight(); break;
case Event.KEY_UP: this.keyUp(); break;
default: return; // don't cancel keypress unless intercepted successfully
}
Event.stop(inEvent);
},
isChildItem: function(inNode){
if (inNode.getAttribute('role') && inNode.getAttribute('role').toLowerCase() == this.childRole) return true;
else return false;
},
keyDown: function() {
var el = this.selectedItem;
this.setSelectedItem(this.getNextItem(el));
},
keyLeft: function() {
var el = this.selectedItem;
this.setSelectedItem(this.getPreviousItem(el));
},
keyRight: function() {
var el = this.selectedItem;
this.setSelectedItem(this.getNextItem(el));
},
keyUp: function() {
var el = this.selectedItem;
this.setSelectedItem(this.getPreviousItem(el));
},
setSelectedItem: function(inNode, inOptDoNotFocus) {
if (this.selectedItem){
this.selectedItem.tabIndex = -1;
Element.removeClassName(this.selectedItem, 'active');
// remove the additional attribute assignments on the active item
for (var i=0, c=this.attributes.length; i<c; i++){
var attr = this.attributes[i];
if (attr.falseValue) {
this.selectedItem.setAttribute(attr.attribute, attr.falseValue); // set each to false
} else {
this.selectedItem.removeAttribute(attr.attribute); // or remove it completely
}
}
}
this.selectedItem = $(inNode) || this.childItems[0];
Element.addClassName(this.selectedItem, 'active');
this.selectedItem.tabIndex = 0;
if (this.selectFunction) {
this.selectFunction(this.childItems);
}
// add the additional attribute assignments on the active item
for (var i=0, c=this.attributes.length; i<c; i++){
var attr = this.attributes[i];
this.selectedItem.setAttribute(attr.attribute, attr.value);
}
if (!inOptDoNotFocus) this.selectedItem.focus();
return this.selectedItem;
}
};