lcdsantos / jQuery-Selectric

jQuery plugin for easy manipulation and customization of HTML selects
http://selectric.js.org/
MIT License
727 stars 157 forks source link

"Blank" screen reader dropdown options #162

Open bewards opened 7 years ago

bewards commented 7 years ago

Using opensource NVDA screen reader on selectric demo page, the options read out "blank" when using arrow keys.

The focus state looks like it's on the "option" markup, but using document.activeElement shows that the focus is on the <body> tag. I had an analysis of WCAG AA done, with the following results:

WCAG criteria fails the following sections: 1.3.1, 4.1.2 Description: Using Safari with Voiceover, Internet Explorer with JAWS or FireFox with NVDA, make a selection from the menu using the Down Arrow key (JAWS, NVDA) or Control+Option+Right Arrow (VO) and press control+option+space (VO) or Space (JAWS, NVDA):

Other than keyboard navigation, is there a possible fix for even just the screen reader reading "blank"? And has there been any talk of accessibility in the works for upcoming releases?

bewards commented 7 years ago

Pardon my non-technical background of this plugin, but if a user is able to key through the custom html options, would it be possible to set focus on the highlighted option via tab-index or using aria-labeledby to read the highlighted option?

lcdsantos commented 7 years ago

Yes, accessibility is something that I would like very much to work on.

However, at the moment, my spare time is pretty limited and I can't work on the project as much as I wanted. By the way, sorry the long delay to answer.

Thank you for your insights. It will be very usefull when this functionality get implemented.

Pull requests are welcomed, if someone wants to work on this 😉

pszoldan commented 6 years ago

We decided to implement proper aria properties for elements, and once done, contribute it back to the community. Feel free to assign this to me. Expect a PR within two weeks.

pszoldan commented 6 years ago

We've made progress on this issue, but it's not ready for a PR yet. If anybody is interested in helping out with testing ( @bewards ? ) or even development, you can grab my fork here https://github.com/pszoldan/jQuery-Selectric

digitaldonkey commented 3 years ago

Couldn't see any improvement with this PR. Ended up implementing ARIA compatibility, by using the API (using selectric 1.13)

      $('.block-facets').each(function (ind, elm) {

        // Aria interaction for selectric.
        // @see https://www.w3.org/TR/wai-aria-practices/examples/combobox/aria1.1pattern/listbox-combo.html#sc3_label
          var
            wrapper = $(elm),
            select_elm = wrapper.find('.facets-dropdown'),
            id_prefix = select_elm.attr('id') ? select_elm.attr('id') : getRandomId(),
            label_id = select_elm.attr('aria-labelledby'),
            listbox_id = id_prefix + '_listbox',
            text_input,
            listbox,
            combobox;

          select_elm.selectric({
            onInit: function (select, selectric) {
              text_input = wrapper.find('.selectric-input');
              text_input.attr('aria-labelledby', label_id);
            },
            onBeforeOpen: function (select, selectric) {
              listbox = wrapper.find('.selectric-scroll > ul');
              combobox = wrapper.find('.selectric');

              // Add fake :active.
              wrapper.addClass('is-focused');
              text_input
                .attr('aria-autocomplete','both')
                .attr('aria-controls',listbox_id)
                .attr('aria-labelledby', label_id)
                .attr('id', id_prefix + '_input')
                .attr('aria-activedescendant','');
              combobox
                .attr('role', 'combobox')
                .attr('aria-expanded', false)
                .attr('aria-owns', false)
                .attr('aria-owns', listbox_id)
                .attr('aria-haspopup', listbox_id)
                .attr('id', id_prefix + '_combobox')
                .attr('aria-expanded', false)
              listbox
                .attr('aria-labelledby', label_id)
                .attr('id', listbox_id);
            },
            onOpen: function () {
              combobox.attr('aria-expanded', true);
            },
            onClose: function () {
              combobox.attr('aria-expanded', false);
            },
            onBeforeClose: function (select, selectric) {
              wrapper.removeClass('is-focused')
            },
            onBeforeHighlight: function (select, selectric) {
              wrapper.find('[aria-selected]').removeAttr('aria-selected');
            },
            onHighlight: function (select, selectric) {
              wrapper.find('[data-index=' + selectric.state.highlightedIdx + ']')
                .find('[role="option"]')
                .attr('aria-selected', true);
              text_input.attr('aria-activedescendant',id_prefix + '_listbox_' + selectric.state.highlightedIdx);
            },
            optionsItemBuilder: function (itemData, element, index) {
              var unselect = (index == 0 && !element.selected) ? 'aria-label="' + Drupal.t('remove filter') + '"' : ''
              return '<span role="option" ' + unselect + ' id="' + id_prefix + '_listbox_' + index + '" >{text}</span>';
            }
          });
      })
    }

    function getRandomId() {
      var charSet = 'abcdefghijklmnopqrstuvwxyz';
      var randomString = '';
      for (var i = 0; i < 12; i++) {
        var randomPoz = Math.floor(Math.random() * charSet.length);
        randomString += charSet.substring(randomPoz, randomPoz + 1);
      }
      return 'facet_' + randomString;
    },