Подтвердить что ты не робот

Получение чтения с экрана для чтения нового контента, добавленного с помощью JavaScript

Когда загружается веб-страница, программа чтения с экрана (например, тот, который поставляется с OS X или JAWS в Windows) будет читать содержимое всей страницы. Но скажите, что ваша страница динамична, и, как пользователи, выполняющие действие, на страницу добавляется новый контент. Для простоты, скажем, вы показываете сообщение где-то в <span>. Как заставить читателя экрана читать это новое сообщение?

4b9b3361

Ответ 1

Спецификация WAI-ARIA определяет несколько способов, которыми читатели экрана могут "смотреть" элемент DOM. Наилучшим поддерживаемым методом является атрибут aria-live. Он имеет режимы off, polite, assertive и rude. Чем выше уровень уверенности, тем больше вероятность прерывания того, что в настоящее время говорит читатель экрана.

В Firefox 3 и Firefox 4.0b9 было протестировано NVDA:

<!DOCTYPE html>
<html>
<head>
  <script src="js/jquery-1.4.2.min.js"></script>
</head>
<body>
  <button onclick="$('#statusbar').html(new Date().toString())">Update</button>
  <div id="statusbar" aria-live="assertive"></div>
</body>

То же самое может быть выполнено с WAI-ARIA roles role="status" и role="alert". У меня были сообщения о несовместимости, но они не смогли воспроизвести их.

<div id="statusbar" role="status">...</div>

Ответ 2

Вот пример адаптированного реального мира - эта надстройка уровня уже была преобразована из неупорядоченного списка со ссылками в меню выбора через JS. Реальный код намного сложнее и, очевидно, не может быть включен во всей его полноте, поэтому помните, что это необходимо пересмотреть для использования в производстве. Чтобы меню выбора было доступным для клавиатуры, мы зарегистрировали события нажатия клавиш и onchange и произнесли вызов AJAX, когда пользователи вышли из списка (остерегайтесь различий браузера во времени события onchange). Это был серьезный PITA, чтобы сделать доступным, но это возможно.

  //  HTML

  <!-- select element with content URL -->
  <label for="select_element">State</label>
  <select id="select_element">
     <option value="#URL_TO_CONTENT_PAGE#" rel="alabama">Alabama</option>
  </select>
  <p id="loading_element">Content Loading</p>

  <!-- AJAX content loads into this container -->
  <div id="results_container"></div>


  // JAVASCRIPT (abstracted from a Prototype class, DO NOT use as-is)

  var selectMenu = $('select_element');
  var loadingElement = $('loading_element');
  var resultsContainer = $('results_container');

 // listen for keypress event (omitted other listeners and support test logic)
  this.selectMenu.addEventListener('keypress', this.__keyPressDetector, false);


 /* event callbacks */

 // Keypress listener

  __keyPressDetector:function(e){

    // if we are arrowing through the select, enable the loading element
    if(e.keyCode === 40 || e.keyCode === 38){
        if(e.target.id === 'select_element'){
            this.loadingElement.setAttribute('tabIndex','0');
        }
    }
    // if we tab off of the select, send focus to the loading element
    //  while it is fetching data
     else if(e.keyCode === 9){
        if(targ.id === 'select_element' && targ.options[targ.selectedIndex].value !== ''){            
            this.__changeStateDetector(e);

            this.loadingElement.focus();

        }   
    }
}

// content changer (also used for clicks)
__changeStateDetector:function(e){

    // only execute if there is a state change
    if(this.selectedState !== e.target.options[e.target.selectedIndex].rel){

       // get state name and file path
       var stateName = e.target.options[e.target.selectedIndex].rel;
       var stateFile = e.target.options[e.target.selectedIndex].value;

       // get the state file
       this.getStateFile(stateFile);

       this.selectedState = stateName;

    }
}

getStateFile:function(stateFile){
    new Ajax.Request(stateFile, {
        method: 'get',
        onSuccess:function(transport){      

            // insert markup into container
            var markup = transport.responseText;

            // NOTE: select which part of the fetched page you want to insert, 
            // this code was written to grab the whole page and sort later

            this.resultsContainer.update(markup);

            var timeout = setTimeout(function(){

                // focus on new content
               this.resultsContainer.focus();

            }.bind(this), 150);

        }.bind(this)
    });
}