Получение программы чтения с экрана для чтения нового контента, добавленного с помощью JavaScript - PullRequest
26 голосов
/ 08 сентября 2010

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

Ответы [ 2 ]

28 голосов
/ 06 января 2011

Спецификация WAI-ARIA определяет несколько способов, с помощью которых программы чтения с экрана могут «наблюдать» за элементом DOM. Лучшим поддерживаемым методом является атрибут aria-live. Имеются режимы off, polite, assertive и rude. Чем выше уровень самоуверенности, тем больше вероятность, что он прервет то, что в данный момент говорит программа чтения с экрана.

Следующее было протестировано с NVDA под Firefox 3 и Firefox 4.0b9:

<!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 ролями role="status" и role="alert". У меня были сообщения о несовместимости, но я не смог их воспроизвести.

<div id="statusbar" role="status">...</div>
1 голос
/ 06 мая 2011

Вот адаптированный пример реального мира - эта разметка верхнего уровня уже была преобразована из неупорядоченного списка со ссылками в меню выбора через JS.Реальный код намного сложнее и, очевидно, не может быть включен целиком, поэтому помните, что его придется переосмыслить для производственного использования.Чтобы сделать меню выбора доступным для клавиатуры, мы зарегистрировали события нажатия клавиш и обмена и вызвали вызов 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)
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...