2010-09-08 113 views
22

加載網頁時,屏幕閱讀器(例如OS X附帶的或Windows上的JAWS)將讀取整個頁面的內容。但是說你的頁面是動態的,並且當用戶執行一個動作時,新的內容被添加到頁面中。爲了簡單起見,假設您在<span>的某處顯示消息。你如何讓屏幕閱讀器閱讀這條新消息?讓屏幕閱讀器讀取使用JavaScript添加的新內容

+0

屏幕閱讀器在獲得焦點時會閱讀表單域和鏈接。所以一種可能性就是在文本上加上一個錨,並將焦點放在該錨上。通過CSS,您可以使鏈接不會顯示爲查看頁面的用戶的鏈接。但是這種方法並不是非常令人滿意,因爲屏幕閱讀器用戶會被誤認爲是鏈接。 – avernet 2010-09-08 17:58:06

+2

將tabindex添加到任何元素,它會變得可讀,我相信(tabindex = -1使其腳本化,但不可tabbable)。我經常以編程方式在單擊鏈接(如選項卡切換器或手風琴)後將焦點發送到新內容 - 但它不一定是可以聚焦的鏈接。閱讀tabindex。 – 2011-04-27 18:52:58

回答

25

WAI-ARIA規範定義了屏幕閱讀器可以「監視」DOM元素的幾種方法。最好的支持方法是aria-live屬性。它有模式off,polite,assertiverude。自信程度越高,越有可能中斷屏幕閱讀器當前正在說的內容。

下已與NVDA火狐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> 

同樣的事情可以用accomplished WAI-ARIA rolesrole="status"role="alert"。我有不相容的報道,但一直沒有能夠複製它們。

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

爲了清楚起見,'aria-live'的唯一有效值是'off','polite'和'assertive'。如果有人對與活動區域相關的角色的默認值感到好奇,甚至只是想看看他們做了什麼,我就寫了一個小遊樂場來展示活動區域:http://schne324.github.io/live-region-play/ – harris 2016-01-12 15:07:29

+0

這對我而言不適用於使用Firefox 41.0.2的Mac,您是否有任何線索?適用於Safari和Chrome – 2016-07-07 15:56:22

+0

只需添加到有效的aria-live值,實際上就有4個值。 **關**,**禮貌**,**自信**和**粗魯**,如文中所述:https://msdn.microsoft.com/en-us/library/windows/apps /hh465711.aspx – 2017-02-24 16:11:26

0

這裏有一個適應現實世界的例子 - 這件事級標記已經從鏈接到通過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) 
    }); 
}