Сделать Select2 pillbox control более доступным и совместимым с отзывами (принесите программу чтения с экрана) - PullRequest
1 голос
/ 27 мая 2020

Мне нужны отзывы об улучшениях программы чтения с экрана для приведенного ниже кода / примера.

Элемент управления pillbox Select2 должен быть более доступным. У них есть нерешенные вопросы по этому вопросу Страница проблемы Select2 , и после получения дополнительных отзывов я отправлю им предложения по изменению (или отправлю ветку с изменениями).

Мои цели в следующем код:

  1. Start to Fini sh Experience
  2. Когда пользователь впервые получает доступ к управлению, ему необходимо прочитать, какие элементы выбраны. last
  3. и вызывает путаницу, будет использовать ROLE, чтобы изменить это.
  4. Дайте пользователю 1 простой способ удалить элемент или все выбранные элементы a. программа чтения с экрана скрывает отдельное удаление, слишком большая путаница вызвала множество способов сделать это.
  5. При выборе ввода дать четкие инструкции по использованию (список фильтров, открытый список, как перемещаться)
  6. Когда динамически сгенерированные доступные элементы открываются, и пользователь перемещается по ним, сообщает им, что выбрано, а что не выбрано. а. Дважды проверьте использование тега Aria. б. Сообщите пользователю, что они могут выбирать и отменять выбор элементов

Мой рабочий пример находится на скрипке js здесь

Также здесь находится рабочая копия

//- nonoandy
$(document).ready(function() {
  //this probobly can be done wiht adapters or smarter ways that will take me a lot longer to do lol. -nonoandy

  //using this class like a flag to stop circuler reference
  var updatedHtmlClass = "select2-skipme";

  //init the select2 control
  var select2Orginal = $(".select2Control");
  select2Orginal.select2();

  //find the real select2 control
  var select2Control = $(".select2Control").next();

  //When screen reader user is arrowing through page (not tabbing through) this will explain the UL
  var select2UlDesc = select2Control.find("span.select2-selection");
  select2UlDesc.prepend("<span class='sr-only'>Selected Items</span>");

  //1. Change the role of the <li> that contains the SearchBox, so screen reader count and reading is more accurate. 
  //2. Warning! I would like to move the SearchBox out of the <UL> and the remove all BUT Select2 doesnt' work right if you move it (change to div would be best too)
  var searchBoxLi = select2Control.find("li.select2-search");
  var searchBoxInput = select2Control.find("input.select2-search__field");
  if (searchBoxLi) {
    //making sure screen reader treat the searchbox <li> as a item
    searchBoxLi.attr("role", "search");

    //adding in flag for future skips
    searchBoxLi.addClass(updatedHtmlClass);
    var searchBoxInput = select2Control.find("input.select2-search__field");
    if (searchBoxInput) {
      //adding in screen reader description to help explain purpose of search box
      var searchDescId = select2Orginal.id + "_SearchBox_desc";
      searchBoxInput.attr("aria-describedby", searchDescId);
      searchBoxLi.append("<div id='" + searchDescId + "' class='sr-only'>Optionally you can type to filter and after activating press Up or Down arrows to select or unselect items</div>")
    }
  }

  //Not tested Yet
  //This <span> is inside the <ul> which isn't good syntax but doens't seem to mess with JAWS screen readers
  var clearAllSpan = select2Control.find("span.select2-selection__clear");
  if (clearAllSpan) {
    clearAllSpan.text("<i class='fas fa-times' aria-hidden='true'></i><span class='sr-only'>Remove all items</span>");
  }

  //When a <li> is added after selection, we need to do a few things
  //1. Update the remove <span> with icon because I like that better
  //2. Aria Hide the  remove-span and leave just selected text for screen readers to find.
  //				WHY!! because they can select and unselect in the dropdown and there is a "remove all" option.  Adding too much stuff makes it confusing. (less is more)
  //3. add class-flags in because circular referenes 
  var selectUl = select2Control.find("ul.select2-selection__rendered");
  $(selectUl).on('DOMNodeInserted', 'li', function(e) {
    //need "Hooks" or events for custom code when a <li> is added
    //DOMNodeInserted is old but faster to uses than MutationObserver #ClearnUp
    if (e.currentTarget.className.indexOf(updatedHtmlClass) == -1) {
      e.currentTarget.className += " " + updatedHtmlClass;
      var newRemoveItemHtml = "<span aria-hidden='true' class='select2-selection__choice__remove' role='presentation' title='Remove " + e.currentTarget.title + "'><i class='fas fa-times'></i></span>" + e.currentTarget.title;
      if (e.currentTarget.innerHTML.indexOf(updatedHtmlClass) == -1) {
        e.currentTarget.innerHTML = newRemoveItemHtml;
      }
    }
  });


  //Select2 dynamically shows a dropdown for selecting or unselecting items
  //I want to make sure this list of items is clearly marked as 'Selected' or 'Not Selected' 
  $('select').on('select2:open', function(e) {
    var dynamixULId = "#" + select2Control.find(".select2-selection").attr("aria-owns");
    $(dynamixULId).on('DOMNodeInserted', 'li', function(e) {
      //AGAIN! need "Hooks" or events for custom code when a <li> is added
      //DOMNodeInserted is old but faster to uses than MutationObserver #ClearnUp
      var currentLi = $(e.currentTarget);

      //it seems the aria-selected is changed after the controls are loaded, so I need a even to trigger and update screen reader text too.
      //attrchange is a older extention there could be better ways of doing this #ResearchLater 
      $(currentLi).attrchange({
        trackValues: true,
        callback: function(event) {
          if (event.attributeName == "aria-selected") {
            if (!currentLi.attr("data-select2-data")) {
              currentLi.attr("data-select2-data", currentLi.text())
            }
            //the aria-selected will make the screen reader say "not selected"
            currentLi.html("<span class='sr-only'>" +
              ((event.newValue == "true") ? "Selected" : "") +
              "</span>" +
              currentLi.attr("data-select2-data"));
          }
        }
      });
    });
  });
});
body {
  /* background: #20262E;*/
  padding: 30px;
  font-family: Helvetica;
}
.select2-results__option[aria-selected="true"]:before {
    content: '\f14a';
    font-family: "Font Awesome 5 Free";
    font-weight: 600;
    padding-right:5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/attrchange/2.0.1/attrchange.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script>



<div id="banner-message">
  <h1>Making the Select2 control more accessible!</h1>
</div>

<div class="form-group">
  <label for="select2Control">
 Pick People 
</label>
  <select id="select2Control" class="select2Control form-control" name="things[]" multiple="multiple">
    <option value="1">Andy</option>
    <option value="2">Bob</option>
    <option value="3">Russ</option>
    <option value="4">Dave</option>
    <option value="5">Matt</option>
    <option value="6">Adam</option>
  </select>
</div>
...