http://www.w3.org/TR/wai-aria-practices/#autocomplete
I got valid pushback from a customer recently wanting to ensure this widget met accessibility standards. It is missing a few Aria tags, and that is it. I may not have time today but hope to find time soon to add a PR that adds the missing components for others. It is keyboard navigable already and I think in a way that meets spec. Just missing are the screenreader aspects.
"The widget has a role of combobox, and its parent role is input. It has a child with role textbox. The property aria-autocomplete indicates whether user input completion suggestions are provided."
EDIT: I should add this is not a problem that Brian has to solve, any of us can and should. I am just logging the issue here so I can track it and get to it myself if no one beats me to it.
Any movement with this? Would be curious to know what is missing to enable Screen Reader support. Thanks
I've semi put together a plugin for this but I would appreciate any guidance.
I'm getting blank in NVDA 2015.3 (Speech Viewer) when I cycle through Selectize options with my keyboard. Also worth noting I'm using optgroups.
Selectize.define('accessibility', function(options){
var self = this;
self.setup = (function(){
var original = self.setup;
return function(){
original.apply(self, arguments);
self.$wrapper.attr({'role': 'application'});
self.$dropdown.attr({'id': 'aria-selectize-dropdown', 'role': 'listbox'});
self.$control_input.attr({
'aria-owns' : 'aria-selectize-dropdown',
'aria-haspopup' : 'true',
'role' : 'combobox',
'aria-autocomplete': 'list'
});
};
})();
});
$('.selectize').selectize({
plugins: {'accessibility': {}},
render: {
option: function($item, escape){
return '<div role="option">' + $item.value + '</div>';
}
}
});
<div class="selectize-control selectize multi plugin-accessibility" role="application">
<div class="selectize-input items not-full has-options">
<input type="text" autocomplete="off" tabindex="" aria-owns="aria-selectize-dropdown" aria-haspopup="true" role="combobox" aria-autocomplete="list" style="width: 4px; opacity: 1; position: relative; left: 0px;" data-cip-id="cIPJQ342845639">
</div>
<div class="selectize-dropdown multi selectize plugin-accessibility" id="aria-selectize-dropdown" role="listbox" style="display: none; width: 945px; top: 34px; left: 0px; visibility: visible;">
<div class="selectize-dropdown-content">
<div data-group="programme_titles.title" class="optgroup">
<div class="optgroup-header">Programme Titles</div>
<div data-value="programme_titles.title.Mathematics" data-selectable="" role="option">Mathematics</div>
<div data-value="programme_titles.title.Mathematics and Philosophy" data-selectable="" role="option">Mathematics and Philosophy</div>
<div data-value="programme_titles.title.Mathematics and Physics" data-selectable="" role="option">Mathematics and Physics</div>
</div>
</div>
</div>
</div>
@kirstenmalin could you help? I saw your commit for Chosen adding accessibility support
@binary-koan could you help? I saw your PR for Select2 adding accessibility support
Hi, sorry for the late reply. I think the key thing you're missing is aria-activedescendant - this needs to be on the input box (or the control which is focused while you're cycling through options) and should contain the ID of the list item which is currently focused. The Google autocomplete lesson was the biggest help with my select2 PR, so it might be worth a read.
Let me know if it works!
Thanks for replying!
Already tried aria-activedescendant with little success (NVDA didn't seem to pick it up) but will try again after I've checked out that link
hi @u01jmg3. have you found a way to have this working?
Nope - the most I could do was write the plugin I have provided
Based on @u01jmg3 script, this is my try to make Selectize accessibile (for my case for now). This script, using the arial-live attribute, trigger also the voiceover while using keyboard to navigate the dropdown list. This is still not perfect but we can work on it. Any one can help ?
You can try it here (CodePen)
(function($, Selectize){
Selectize.define('accessibility', function(options) {
var self = this;
if(typeof this.accessibility === 'undefined') {
this.accessibility = {};
}
this.accessibility.helpers = {
randomId: function(opt) {
var opt = opt || {};
var str = '';
var base = {
base62: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
base36: 'abcdefghijklmnopqrstuvwxyz0123456789',
base10:'0123456789'
}
opt.length = opt.length || 10;
opt.strBase = base[opt.base] || base['base36'];
opt.baseLength = opt.strBase.length;
for(var i = 0; i < opt.length; i++) str += opt.strBase[Math.floor(opt.baseLength * Math.random())];
return str;
}
};
this.accessibility.liveRegion = {
$region: '',
announce: function(msg, expire) {
var $msg = $('<div>' + msg + '</div>');
self.accessibility.liveRegion.$region.append($msg);
setTimeout(function() {
self.accessibility.liveRegion.$region.empty();
}, expire || 3000);
},
setAttributes: function() {
self.accessibility.liveRegion.$region.attr({
'aria-live': 'assertive',
'role': 'log',
'aria-relevant': 'additions',
'aria-atomic': 'false'
})
},
setStyle: function() {
self.accessibility.liveRegion.$region.css({
'position': 'absolute',
'width': '1px',
'height': '1px',
'margin-top': '-1px',
'clip': 'rect(1px, 1px, 1px, 1px)',
'overflow': 'hidden'
});
},
eventsHandler: function(){
var mut = new MutationObserver(function(mutations){
mutations.forEach(function(mutation) {
var $target = $(mutation.target);
if($target.hasClass('active')) {
self.accessibility.liveRegion.announce($target.text(), 500);
}
if($target.hasClass('selected') && !mutation.oldValue.match('selected')) {
self.$dropdown_content.find('[aria-selected]').attr('aria-selected', 'false');
setTimeout(function(){
$target.attr('aria-selected', true);
}, 0);
}
});
});
mut.observe(self.$dropdown[0],{
attributeFilter: ['class'],
subtree: true,
attributeOldValue: true
});
},
init: function(options) {
self.accessibility.liveRegion.$region = $('<div>');
self.accessibility.liveRegion.setAttributes();
self.accessibility.liveRegion.setStyle();
self.accessibility.liveRegion.eventsHandler();
$('body').append(self.accessibility.liveRegion.$region);
}
}
this.setup = (function() {
var original = self.setup;
return function(){
original.apply(this, arguments);
var id = self.accessibility.helpers.randomId();
self.$control_input.attr({
'role': 'combobox',
'aria-owns': id,
'aria-autocomplete': 'list',
'aria-expanded': 'false',
'aria-labelledby': 'country'
});
self.$dropdown_content.attr({
'role': 'listbox',
'id': id
});
self.accessibility.liveRegion.init();
};
})();
});
})(jQuery, Selectize);
$('select').selectize({
plugins: {'accessibility': {}},
render: {
option: function($item, escape) {
return `<div class="option" role="option" aria-selected="false">${$item.text}</div>`
}
}
});
@SLMNBJ Your script helped me out big time! Great start and I hope they get something figured out/rolled into the actual library... this is a huge issue for me and will probably prevent me from using it on further projects.
Hi @laurelstreng,
It's a pleasure to read it. You can follow the project here https://github.com/SLMNBJ/selectize-plugin-a11y. We are developing a second version. More robust, adding custom labes and support native Selectize events.
Magnificent, thank you for making this plugin @SLMNBJ
Bump....
Probably will have to consider other plugins that has no issues - as WCAG 2.1 AA is an EU requirement,
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days
Most helpful comment
Based on @u01jmg3 script, this is my try to make Selectize accessibile (for my case for now). This script, using the arial-live attribute, trigger also the voiceover while using keyboard to navigate the dropdown list. This is still not perfect but we can work on it. Any one can help ?
You can try it here (CodePen)