codesite...@google.com
unread,Nov 13, 2008, 10:51:49 AM11/13/08Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to jquery...@googlegroups.com
Author: david.bolter
Date: Thu Nov 13 07:51:09 2008
New Revision: 931
Modified:
trunk/tests/accordion.js
trunk/ui/ui.accordion.js
Log:
Added accordion keyboard and ARIA support, and tests. Mozilla needs this
for website. (partial review: Scott González, fix for 3553)
Modified: trunk/tests/accordion.js
==============================================================================
--- trunk/tests/accordion.js (original)
+++ trunk/tests/accordion.js Thu Nov 13 07:51:09 2008
@@ -129,4 +129,22 @@
.accordion("activate", 0);
});
+test("accessibility", function () {
+ expect(9);
+ var ac = $('#list1').accordion().accordion("activate", 1);
+ var headers = $(".ui-accordion-header");
+
+ equals( headers.eq(1).attr("tabindex"), "0", "active header should have
tabindex=0");
+ equals( headers.eq(0).attr("tabindex"), "-1", "inactive header should
have tabindex=-1");
+ equals( ac.attr("role"), "tablist", "main role");
+ equals( headers.attr("role"), "tab", "tab roles");
+ equals( headers.next().attr("role"), "tabpanel", "tabpanel roles");
+ equals( headers.eq(1).attr("aria-expanded"), "true", "active tab has
aria-expanded");
+ equals( headers.eq(0).attr("aria-expanded"), "false", "inactive tab has
aria-expanded");
+ ac.accordion("activate", 0);
+ equals( headers.eq(0).attr("aria-expanded"), "true", "newly active tab
has aria-expanded");
+ equals( headers.eq(1).attr("aria-expanded"), "false", "newly inactive tab
has aria-expanded");
+});
+
+
})(jQuery);
Modified: trunk/ui/ui.accordion.js
==============================================================================
--- trunk/ui/ui.accordion.js (original)
+++ trunk/ui/ui.accordion.js Thu Nov 13 07:51:09 2008
@@ -41,7 +41,7 @@
this.element.addClass("ui-accordion");
$('<span class="ui-accordion-left"/>').insertBefore(options.headers);
$('<span class="ui-accordion-right"/>').appendTo(options.headers);
- options.headers.addClass("ui-accordion-header").attr("tabindex", "0");
+ options.headers.addClass("ui-accordion-header");
}
var maxHeight;
@@ -60,23 +60,83 @@
maxHeight = Math.max(maxHeight, $(this).outerHeight());
}).height(maxHeight);
}
+
+ this.element.attr('role','tablist');
+
+ var self=this;
+ options.headers
+ .attr('role','tab')
+ .bind('keydown', function(e) { return self._keydown(e); })
+ .next()
+ .attr('role','tabpanel');
options.headers
.not(options.active || "")
+ .attr('aria-expanded','false')
+ .attr("tabIndex", "-1")
.next()
.hide();
- options.active.parent().andSelf().addClass(options.selectedClass);
+
+ // make sure at least one header is in the tab order
+ if (!options.active.length) {
+ options.headers.eq(0).attr('tabIndex','0');
+ } else {
+ options.active
+ .attr('aria-expanded','true')
+ .attr("tabIndex", "0")
+ .parent().andSelf().addClass(options.selectedClass);
+ }
+
+ // only need links in taborder for Safari
+ if (!$.browser.safari)
+ options.headers.find('a').attr('tabIndex','-1');
if (options.event) {
this.element.bind((options.event) + ".accordion", clickHandler);
}
},
+
+ _keydown: function(e) {
+ if (this.options.disabled || e.altKey || e.ctrlKey)
+ return;
+
+ var keyCode = $.keyCode;
+
+ var length = this.options.headers.length;
+ var currentIndex = this.options.headers.index(e.target);
+ var toFocus = false;
+
+ if (e.keyCode == keyCode.RIGHT || e.keyCode == keyCode.DOWN){
+
+ toFocus = this.options.headers[(currentIndex + 1) % length];
+
+ } else if (e.keyCode == keyCode.LEFT || e.keyCode == keyCode.UP) {
+
+ toFocus = this.options.headers[(currentIndex - 1 + length) % length];
+
+ } else if (e.keyCode == keyCode.SPACE || e.keyCode == keyCode.ENTER) {
+
+ return clickHandler.call(this.element[0], { target: e.target });
+
+ }
+
+ if (toFocus) {
+ $(e.target).attr('tabIndex','-1');
+ $(toFocus).attr('tabIndex','0');
+ toFocus.focus();
+ return false;
+ }
+
+ return true;
+ },
+
activate: function(index) {
// call clickHandler with custom event
clickHandler.call(this.element[0], {
target: findActive( this.options.headers, index )[0]
});
},
+
destroy: function() {
this.options.headers.parent().andSelf().removeClass(this.options.selectedClass);
this.options.headers.prev(".ui-accordion-left").remove();
@@ -189,6 +249,8 @@
}
complete(true);
}
+ toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1");
+ toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();;
}
function clickHandler(event) {