This topic describes how you can optimize your application for the Samsung Smart TV text-to-speech (TTS) voice guide feature. The TTS feature is helpful for users with visual limitations, since they can have difficulty using textual on-screen TV features.
Smart TVs support the accessibility toolkit (ATK) as part of the Web engine. If the user has activated the voice guide feature, the text-to-speech (TTS) engine can read HTML elements on the application screen.
Not all TV models support the voice guide feature.
To support the voice guide feature in your app:
You must set automatic focus to an HTML element when the app is launched. To achieve this, set HTML’s autofocus attribute on one of the app’s elements.
Example:
<button type="button" autofocus>Click Me!</button>
Referral link: https://www.w3schools.com/tags/att_autofocus.asp
This API must be used, otherwise, voice guide will behave unexpectedly when launching the web app.
To test the voice guide feature:
<div id="test" tabindex="-1" >TTS Test</div>
document.getElementById("test").focus(); // javascript // OR $("#test").focus(); // jQuery
<div id="test" tabindex="-1" > TTS Test <div> Second Element.</div> </div>
document.getElementById("test").focus(); // javascript
The voice guide ignores elements hidden using the display: none property.
display: none
You can support more complex voice guide functionality by implementing roles and descriptions based on the WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) standard for Web content accessibility.
By default, the voice guide reads content in the focused HTML element in the following order:
Name The element name and description are calculated using the rules defined in Accessible Name and Description Computation, although older Web engines do not follow the specification completely.
Role To inform the TTS engine that an HTML element has description information, define a role for the element using the ARIA role attributes. If an HTML element does not have a defined role attribute, the Web engine maps a role to it based on the W3C standard HTML Element Role Mappings.
Description Additional information to be read by the voice guide can be implemented using ARIA states and properties.
If an HTML element does not have a defined name or label, the Web engine can calculate a name from the element content, if the defined role supports it. Only some roles support calculate a name from content
The following examples show how an HTML element can be assigned a name from its content:
In the following code, the outer div element does not have a role defined. The voice guide says: "Section".
div
<div id="thumb:0" class="homeThumb" tabindex="2000" style="cursor: pointer;"> <div class="thumbImage"><img id="thumb:img:0" src="http://network.wwe.com/assets/images/1/7/8/263558178/cuts/215x121/cut.jpg" class="thumbImage"></div> <div class="thumbRule"></div> <div class="thumbTitle">FEATURED</div> <!--%--> </div>
In the following code, the "button" role is defined for the outer div element. Since the "button" role supports name from content, the voice guide says: "Featured button".
<div id="thumb:0" class="homeThumb" tabindex="2000" style="cursor: pointer;" role="button"> <div class="thumbImage"><img id="thumb:img:0" src="http://network.wwe.com/assets/images/1/7/8/263558178/cuts/215x121/cut.jpg" class="thumbImage"></div> <div class="thumbRule"></div> <div class="thumbTitle">FEATURED</div> <!--%--> </div>
For compatibility with older TV Web engines that do not fully support the W3C specification, since Tizen 3.0, you can define an empty role attribute (role=""). The voice guide calculates the element name from the content, and does not say a role name. In the following code, the voice guide says: "Featured".
role
role=""
<div id="thumb:0" class="homeThumb" tabindex="2000" style="cursor: pointer;" role=""> <div class="thumbImage"><img id="thumb:img:0" src="http://network.wwe.com/assets/images/1/7/8/263558178/cuts/215x121/cut.jpg" class="thumbImage"></div> <div class="thumbRule"></div> <div class="thumbTitle">FEATURED</div> <!--%--> </div>
Some HTML elements cannot be focused. To make the element focusable, implement the tabindex attribute:
tabindex
In the following example, the voice guide says: "Aria Test, menuitem, this is the aria label".
<div id="test" tabindex="-1" role="menuitem" aria-label ="this is the aria label"> Aria Test </div>
document.getElementById("test").focus(); // javascrip
If you assign the value "-1" to the tabindex attribute, the element can only be focused using JavaScript, and not with the "Tab" key. If you want to implement sequential navigation with the "Tab" key, the tabindex attribute must have a positive value. Since there is no "Tab" key on a remote control, you must consider how to implement focus movement.
The following popup window uses the tabindex attribute to make the button focusable with JavaScript. When the button in the popup has focus, the voice guide says: "Error Message title, Lorem ipsum dolor sit amet, consectetur adipisicing elit, Button Text, select to close".
<div id="popup" class="popup"> <div id="popupTitle" class="title"> Error Message title </div> <div id="popupText" class="text"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. </div> <div id="popupButton" role="button" tabindex="-1" class="button"> <div aria-labelledby="popupTitle popupText"></div> <div class="">Button Text</div> <div aria-label=", select to close."></div> </div> </div>
document.getElementById("popupButton").focus(); // javascript
In general, you do not need to implement additional code to handle enabling and disabling the voice guide in your application, since it is handled with the TV menu setting. However, you can check whether the voice guide is enabled.
To check whether the voice guide is enabled, use the getMenuValue() method with the TvInfoMenuKey.VOICE_GUIDE_KEY property:
getMenuValue()
TvInfoMenuKey.VOICE_GUIDE_KEY
// Returns "true" if voice guide is enabled webapis.tvinfo.getMenuValue(webapis.tvinfo.TvInfoMenuKey.VOICE_GUIDE_KEY);
To be notified when the voice guide is switched on or off:
var listenerId = ''; var onChange = function() { // Gets true or false status webapis.tvinfo.getMenuValue(webapis.tvinfo.TvInfoMenuKey.VOICE_GUIDE_KEY); }; try { listenerId = webapis.tvinfo.addCaptionChangeListener(webapis.tvinfo.TvInfoMenuKey.VOICE_GUIDE_KEY, onChange); console.log("listener id = " + listenerId); } catch (error) { console.log(" error code = " , error); }
This section describes the support for various ARIA role attributes and their behavior, as implemented in NVDA for Windows® computers and on Tizen. The behavior descriptions are based on the example scenarios provided.
For the complete list of roles, see Definition of Roles.
Since landmark navigation is not supported on Samsung TVs, the following roles are not supported:
alert Example scenario: Alert Example
Table 1. "alert" attribute behavior
alertdialog Example scenario: Using WAI-ARIA role="alertdialog" to Identify Errors
Table 2. "alertdialog" attribute behavior
application
Table 3. "application" attribute behavior
article Example scenario: Recommended Restaurants
Table 4. "article" attribute behavior
button Example scenario: Button Examples
Table 5. "button" attribute behavior
checkbox Example scenario: Checkbox Example (Mixed-State)
Table 6. "checkbox" attribute behavior
combobox Example scenario: Legacy ARIA 1.0 Combobox With Both List and Inline Autocomplete Example
Table 7. "combobox" attribute behavior
dialog Example scenario: Modal Dialog Example
Table 8. "dialog" attribute behavior
grid and grid-cell Example scenario: Layout Grid Examples
grid
Table 9. "grid" and "gridcell" attribute behavior
img Example scenario:
<div class="sprite card_icons amex" tabindex="0" role="img" aria-label="American Express"></div>
Table 10. "img" attribute behavior
link Example scenario: ARIA Example: link role
Table 11. "link" attribute behavior
list and listitem Example scenario:
<div class="list" role="list"> <div tabindex="0" role="listitem">first item</div> <div tabindex="0" role="listitem">second item</div> <div tabindex="0" role="listitem">third item</div> </div>
Table 12. "list" and "listitem" attribute behavior
listbox Example scenario: Listbox Example
aria-activedescendant
listbox
Table 13. "listbox" attribute behavior
log Example scenario: Live Regions
Table 14. "log" attribute behavior
marquee No information.
math Example scenario:
<div tabindex="0" role="math" aria-label="6 divided by 4 equals 1.5"> \frac{6}{4}=1.5 </div>
aria-label
Table 15. "math" attribute behavior
menu, menubar, and menuitem Example scenario: Navigation Menubar Example
Table 16. "menu", "menubar, and "menuitem" attribute behavior
menuitemcheckbox and menuitemradio Example scenario: Editor Menubar Example
Table 17. "menuitemcheckbox" and "menuitemradio" attribute behavior
none and presentation Example scenario:
<div> <p role="none"> This is paragraph text. Role of "none" is set on this text. </p> </div>
Table 18. "none" and "presentation" attribute behavior
note Not supported.
option Example scenario: Listbox Example
<item name>
Table 19. "option" attribute behavior
progressbar
Table 20. "progressbar" attribute behavior
radio and radiogroup Example scenario: ARIA radiogroup and radio Example
radiogroup
Table 21. "radio" attribute behavior
row, rowgroup, columnheader, and rowheader Example scenario: Layout Grid Examples
Table 22. "row", "rowgroup", "columnheader", and "rowheader" attribute behavior
scrollbar Example scenario: Scrollable Listbox Example
Table 23. "scrollbar" attribute behavior
searchbox Not supported.
slider Example scenario: Slider Examples with aria-orientation and aria-valuetext
aria-valuetext
Table 24. "slider" attribute behavior
spinbutton
Table 25. "spinbutton" attribute behavior
status No information.
switch
Table 26. "switch" attribute behavior
tab, tablist, and tabpanel
Table 27. "tab", "tablist", and "tabpanel" attribute behavior
table and cell Example scenario: NVDA Practice: Tables
Table 28. "table" and "cell" attribute behavior
textbox Example scenario: ARIA Textbox
Table 29. "textbox" attribute behavior
term Not supported.
timer No information.
toolbar Example scenario: Toolbar Example
Table 30. "toolbar" attribute behavior
tooltip
Table 31. "tooltip" attribute behavior
tree, treegrid, and treeitem
Table 32. "tree", "treegrid", and "treeitem" attribute behavior
This section describes the support for various ARIA state and property attributes and their behavior, as implemented in JAWS for Windows® computers and on Tizen. The behavior descriptions are based on the example scenarios provided.
aria-activedescendant Example scenario: Radio Group Example Using aria-activedescendant
Table 33. "aria-activedescendant" attribute behavior
aria-atomic
Table 34. "aria-atomic" attribute behavior
aria-autocomplete
Table 35. "aria-autocomplete" attribute behavior
aria-busy Example scenario:
<script> var isBusy = 1; function update1() { if (isBusy == 1) { isBusy = 0; document.getElementById("test").setAttribute("aria-busy","false"); document.getElementById("updateBusyButton").innerHTML="Update aria-busy tag, current is false"; } else { isBusy = 1; document.getElementById("test").setAttribute("aria-busy","true"); document.getElementById("updateBusyButton").innerHTML="Update aria-busy tag, current is true"; } } var numFlag = 1; function update2() { numFlag = numFlag + 1; document.getElementById("num").innerHTML=numFlag; } </script> <div id="test" tabindex="0" aria-busy="true" role="" aria-live="polite"> Test aria-busy, if aria-busy is true, content changes are not read <div id="num"> 1 </div> </div> <button id="updateBusyButton" onclick="update1();">Update aria-busy tag, current is true</button> <button id="updateContentButton" onclick="update2();">Update test target content</button>
aria-busy
true
false
Table 36. "aria-busy" attribute behavior
aria-checked
Table 37. "aria-checked" attribute behavior
aria-controls
Table 38. "aria-controls" attribute behavior
aria-current Example scenario: Breadcrumb Example
Table 39. "aria-current" attribute behavior
aria-describedby Example scenario:
<li id="li1"> Check out the video report for last year's <a href="festival.htm" aria-describedby="li1">National Folk Festival</a>. </li>
aria-labelledby
Table 40. "aria-describedby" attribute behavior
aria-disabled Example scenario: Attribute: aria-disabled
Table 41. "aria-disabled" attribute behavior
aria-dropeffect
Table 42. "aria-dropeffect" attribute behavior
aria-expanded
Table 43. "aria-expanded" attribute behavior
aria-flowto Example scenario: Using aria-flowto to give users a choice of reading order
Table 44. "aria-flowto" attribute behavior
aria-grabbed
Table 45. "aria-grabbed" attribute behavior
aria-haspopup Example scenario: Simple dropdowns
Table 46. "aria-haspopup" attribute behavior
aria-hidden Example scenario:
<html> <body onload="focusdiv()"> <div id="test" tabindex="0" role=""> <div aria-hidden="true"> on </div> <div> off <div>child</div> </div> </div> <script> function focusdiv() { document.getElementById("test").focus() } </script> </body> </html>
Table 47. "aria-hidden" attribute behavior
aria-invalid Example scenario: Forms: Using aria-invalid to identify failed fields
Table 48. "aria-invalid" attribute behavior
aria-label Example scenario:
<html> <button aria-label="Close">X</button> </html>
Table 49. "aria-label" attribute behavior
aria-labelledby Example scenario:
<html> <div id="billing">Billing Address</div> <div> <div id="name">Name</div> <input type="text" aria-labelledby="billing name"/> </div> <div> <div id="address">Address</div> <input type="text" aria-labelledby="billing address"/> </div> </html>
Table 50. "aria-labelledby" attribute behavior
aria-level Example scenario:
<button role="heading" aria-level="1">text</button>
Table 51. "aria-level" attribute behavior
aria-live Example scenario: Alert Example
Table 52. "aria-live" attribute behavior
aria-multiline Not supported.
aria-multiselectable Example scenario: ARIA Multiselectable Listbox Example
Table 53. "aria-multiselectable" attribute behavior
aria-orientation Example scenario: Slider Examples with aria-orientation and aria-valuetext
Table 54. "aria-orientation" attribute behavior
aria-owns Example scenario:
<div class="example"> <div role="list"> <div role="listitem" tabindex="0" aria-owns="fruit">Fruit</div> <div role="listitem" tabindex="0">Vegetables</div> </div> <div role="list" id="fruit" tabindex="0"> <div role="listitem" tabindex="0">Apples</div> <div role="listitem" tabindex="0">Bananas</div> </div> </div>
Table 55. "aria-owns" attribute behavior
aria-posinset Example scenario:
<h2 id="label_fruit"> Available Fruit </h2> <ul role="listbox" aria-labelledby="label_fruit"> <li role="option" aria-setsize="16" aria-posinset="5" tabindex="0">apples</li> <li role="option" aria-setsize="16" aria-posinset="6" tabindex="0">bananas</li> <li role="option" aria-setsize="16" aria-posinset="7" tabindex="0">cantaloupes</li> <li role="option" aria-setsize="16" aria-posinset="19" tabindex="0">dates</li> </ul>
Table 56. "aria-posinset" attribute behavior
aria-pressed
Table 57. "aria-pressed" attribute behavior
aria-readonly Example scenario:
<h2>Input text field and textarea with the aria-readonly="true" attribute.</h2> <div> <label for="textField3">First Name</label><br> <input type="text" id="textField3" value="Unknown" aria-readonly="true"></input> </div>
Table 58. "aria-readonly" attribute behavior
aria-relevant
Table 59. "aria-relevant" attribute behavior
aria-required
Table 60. "aria-required" attribute behavior
aria-selected
Table 61. "aria-selected" attribute behavior
aria-setsize Example scenario:
Table 62. "aria-setsize" attribute behavior
aria-sort Example scenario: Data Grid Examples
Table 63. "aria-sort" attribute behavior
aria-valuemax and aria-valuemin Not supported.
aria-valuenow and aria-valuetext Example scenario: Slider Examples with aria-orientation and aria-valuetext
aria-valuenow
Table 64. "aria-valuenow" and "aria-valuetext" attribute behavior