1
0
mirror of synced 2024-11-23 05:26:10 +03:00

Accessibility enhancements for single-value elements. Added correct ARIA attributes and associations. Much-improved screen-reader support (tested with NVDA on Firefox 25)

This commit is contained in:
Jonathan Mahoney 2013-11-06 12:55:12 +00:00
parent 4059d81e6b
commit 78ccc05e04

View File

@ -876,9 +876,12 @@ the specific language governing permissions and limitations under the Apache Lic
if (disabled) { node.addClass("select2-disabled"); } if (disabled) { node.addClass("select2-disabled"); }
if (compound) { node.addClass("select2-result-with-children"); } if (compound) { node.addClass("select2-result-with-children"); }
node.addClass(self.opts.formatResultCssClass(result)); node.addClass(self.opts.formatResultCssClass(result));
node.attr("role", "presentation");
label=$(document.createElement("div")); label=$(document.createElement("div"));
label.addClass("select2-result-label"); label.addClass("select2-result-label");
label.attr("id", "select2-result-label-" + nextUid());
label.attr("role", "option");
formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup); formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup);
if (formatted!==undefined) { if (formatted!==undefined) {
@ -1465,6 +1468,9 @@ the specific language governing permissions and limitations under the Apache Lic
choice = $(choices[index]); choice = $(choices[index]);
choice.addClass("select2-highlighted"); choice.addClass("select2-highlighted");
// ensure assistive technology can determine the active choice
this.search.attr("aria-activedescendant", choice.find(".select2-result-label").attr("id"));
this.ensureHighlightVisible(); this.ensureHighlightVisible();
data = choice.data("select2-data"); data = choice.data("select2-data");
@ -1809,14 +1815,15 @@ the specific language governing permissions and limitations under the Apache Lic
}).html([ }).html([
"<a href='javascript:void(0)' onclick='return false;' class='select2-choice' tabindex='-1'>", "<a href='javascript:void(0)' onclick='return false;' class='select2-choice' tabindex='-1'>",
" <span class='select2-chosen'>&nbsp;</span><abbr class='select2-search-choice-close'></abbr>", " <span class='select2-chosen'>&nbsp;</span><abbr class='select2-search-choice-close'></abbr>",
" <span class='select2-arrow'><b></b></span>", " <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>",
"</a>", "</a>",
"<input class='select2-focusser select2-offscreen' type='text'/>", "<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />",
"<div class='select2-drop select2-display-none'>", "<div class='select2-drop select2-display-none'>",
" <div class='select2-search'>", " <div class='select2-search'>",
" <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'/>", " <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'",
" aria-autocomplete='list' title='Search field' />",
" </div>", " </div>",
" <ul class='select2-results'>", " <ul class='select2-results' role='listbox'>",
" </ul>", " </ul>",
"</div>"].join("")); "</div>"].join(""));
return container; return container;
@ -1919,7 +1926,9 @@ the specific language governing permissions and limitations under the Apache Lic
var selection, var selection,
container = this.container, container = this.container,
dropdown = this.dropdown; dropdown = this.dropdown,
idSuffix = nextUid(),
elementLabel;
if (this.opts.minimumResultsForSearch < 0) { if (this.opts.minimumResultsForSearch < 0) {
this.showSearch(false); this.showSearch(false);
@ -1931,12 +1940,22 @@ the specific language governing permissions and limitations under the Apache Lic
this.focusser = container.find(".select2-focusser"); this.focusser = container.find(".select2-focusser");
// rewrite labels from original element to focusser // add aria associations
this.focusser.attr("id", "s2id_autogen"+nextUid()); selection.find(".select2-chosen").attr("id", "select2-chosen-"+idSuffix);
this.focusser.attr("aria-labelledby", "select2-chosen-"+idSuffix);
this.results.attr("id", "select2-results-"+idSuffix);
this.search.attr("aria-owns", "select2-results-"+idSuffix);
$("label[for='" + this.opts.element.attr("id") + "']") // rewrite labels from original element to focusser
this.focusser.attr("id", "s2id_autogen"+idSuffix);
elementLabel = $("label[for='" + this.opts.element.attr("id") + "']")
.attr('for', this.focusser.attr('id')); .attr('for', this.focusser.attr('id'));
// Ensure the original element retains an accessible name
var originalTitle = this.opts.element.attr("title");
this.opts.element.attr("title", (originalTitle || elementLabel.text()));
this.focusser.attr("tabindex", this.elementTabIndex); this.focusser.attr("tabindex", this.elementTabIndex);
this.search.on("keydown", this.bind(function (e) { this.search.on("keydown", this.bind(function (e) {