2010-09-08 20 views
22

Po załadowaniu strony internetowej czytniki ekranu (takie jak ten dostarczany z systemem OS X lub JAWS w systemie Windows) odczytują zawartość całej strony. Powiedzmy jednak, że strona jest dynamiczna, a użytkownicy wykonujący akcję dodają nową zawartość do strony. Dla uproszczenia, powiedz, że wyświetlasz komunikat gdzieś w numerze <span>. Jak uzyskać czytnik ekranu do odczytania tej nowej wiadomości?Pobieranie czytnika ekranu w celu odczytania nowej zawartości za pomocą JavaScript

+0

Czytniki ekranowe czytają pola formularzy i łącza, gdy uzyskają ostrość. Tak więc jedną z możliwości jest umieszczenie kotwicy wokół tekstu i skupienie się na tej kotwicy. Dzięki CSS możesz uzyskać link, który nie będzie wyświetlany jako link dla użytkowników przeglądających stronę. Ale ta metoda nie jest zbyt satysfakcjonująca, ponieważ użytkownicy czytników ekranu będą błędnie wierzyć, że jest to link. – avernet

+2

Dodaj tabindeks do dowolnego elementu i stanie się czytelny, jak sądzę (tabindex = -1 powoduje, że jest skryptowalny, ale nie tabbable). Często programowo wysyłam fokus do nowej treści po kliknięciu łącza (jak przełącznik kart lub akordeon) - ale nie musi to być link do ustawienia ostrości. Czytaj na tabindex. –

Odpowiedz

25

Specyfikacja WAI-ARIA definiuje kilka sposobów, za pomocą których czytniki ekranu mogą "oglądać" element DOM. Najlepszą obsługiwaną metodą jest atrybut aria-live. Ma tryby: off, polite, assertive i rude. Im wyższy poziom asertywności, tym bardziej prawdopodobne jest przerwanie tego, co jest aktualnie czytane przez czytnik ekranu.

Poniższa został przetestowany z NVDA w Firefoksie 3 i 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> 

To samo może być accomplished z WAI-ARIA rolesrole="status" i role="alert". Miałem raporty o niezgodności, ale nie udało mi się ich odtworzyć.

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

Dla jasności, jedynymi prawidłowymi wartościami dla 'aria-live' są' off', 'grzeczny' i' asertywny'. Jeśli ktoś jest ciekawy domyślnych ról związanych z regionami na żywo, a nawet chce tylko zobaczyć, co robi, napisałem mały plac zabaw, który pokazuje aktywne regiony na żywo: http://schne324.github.io/live-region-playground/ – harris

+0

To nie działa dla mnie na Macu z Firefoksem 41.0.2 czy masz jakąkolwiek wskazówkę? Działa dobrze z przeglądarkami Safari i Chrome. –

+0

Aby dodać prawidłowe wartości dla Aria-Live, istnieją 4 wartości. ** wyłączone **, ** uprzejme **, ** asertywne ** i ** niegrzeczne **, jak odnotowano w dokumentach tutaj: https://msdn.microsoft.com/en-us/library/windows/apps /hh465711.aspx –

0

Oto przykład dostosowany prawdziwy świat - to się na poziomie markup został już przekształcony z nieuporządkowanej listy z linkami do wybierz menu poprzez JS. Rzeczywisty kod jest dużo bardziej złożony i oczywiście nie można go w całości uwzględnić, więc pamiętaj, że będzie to musiało zostać ponownie przemyślane do wykorzystania w produkcji. Aby menu wyboru było dostępne na klawiaturze, zarejestrowaliśmy zdarzenia zmiany stanu klawiatury i wywołaliśmy wywołanie AJAX, gdy użytkownicy wybrali się z listy (uwaga na różnice w czasie wyświetlania zdarzeń onchange). To była poważna PITA, aby była dostępna, ale jest to możliwe.

// 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) 
    }); 
}