Mobile Test 2: Hiding and Displaying Content
This is an improved version of the previous test page. On the previous page, users can toggle the search and navigation features by clicking or tapping their corresponding icons, but VoiceOver users are provided with too little information and feedback.
Here are some changes I made to improve accessibility of this interface:
- Added role="button" to each of the toggle images. Now VoiceOver announces these icons as "Search button" and "Menu button", which may seem subtle, but now the user knows that these are interactive objects.
- To reinforce that these buttons are interactive, I changed the alt attribute so it's more action-oriented ("Show search" and "Show menu" respectively)
- Also added jQuery code to change the alt text to "Hide search" or "Hide menu" when either feature is made visible.
- When a user taps a button to show a feature, that feature should immediately receive focus, since presumably the user wouldn't have tapped it if they didn't want to use it. So, I added jQuery code that places focus in the target element after that element becomes visible. This doesn't work in iOS 4.x (tested on an iPad running 4.3.3) but it works in 5.1.1. For search, focus is placed in the input field, which results in the on-screen keyboard being automatically displayed; and for the menu, focus is played on the first item in the menu.
- Unfortunately, VoiceOver in iOS 5.1.1 is not reliably following the change in focus. When the search field appears and receives focus and the on-screen keyboard appears, VoiceOver says nothing to indicate that this has happened. When the menu appears and receives focus, VoiceOver's focus often remains on the Show Menu button. After exploring this further, I discovered that if both search and menu are visible by default, I can give both fields focus by tapping their corresponding button. In this case VoiceOver works perfectly. However, when these elements are hidden, VoiceOver can't seem to give them focus, even if a delay is introduced to give the hidden elements plenty of time to become visible before trying to give them focus. I played with this for a while on my VoiceOver Dynamic Focus Test page, and ultimately I think I've concluded that:
- VoiceOver will announce the search field's label (or in this example, title) after the form becomes visible and the input receives focus, but only in iOS 5.1.1 (not in 4.3.3), and it only seems to work in landscape mode (my tests failed 100% of the time in portrait mode on the iPhone)
- VoiceOver will not announce the first item in the menu when it receives focus, no matter what the circumstances.
- Added additional ARIA to clarify relationships between all the parts. On each of the elements that are initially hidden, I added aria-hidden="true" and a unique id attribute. On each of the buttons, I added aria-controls="id_X" where id_X is the id of the hidden element that each button controls. It's not clear whether this extra markup has a significant impact on how VoiceOver (or other screen readers) handles the content, but it's all good information that screen readers can use as they see fit (and hopefully will, if they don't already). Also added JQuery code to dynamically change the value of aria-hidden from false to true and back.
- Tried adding aria-haspopup="true" to each of the buttons, but I don't think the hidden content is technically a popup. VoiceOver identifies each button as a "popup button" (e.g., "Show Search popup button"), and if users tap either button to toggle an element visible VoiceOver provides some additional help: "Double tap to activate the picker." This is misleading in the current context because the popup content isn't a picker, which reinforces that this probably isn't correct usage of aria-haspopup. So ultimately I decided not to use this.
- Tried adding aria-expanded="false" to each of the hidden elements (in addition to aria-hidden="true"), but this adversely affected VoiceOver's ability to focus. When a user taps the search button to show search, the newly visible search field receives focus. But with aria-expanded introduced, this change of focus fails and the user is taken to the top of the page. This might be a VoiceOver bug, or it might be that I'm using aria-expanded incorrectly.
- Tried adding aria-pressed="false" to each button, then toggling that to aria-pressed="true" after the user taps to show content, but this resulted in VoiceOver announcing each button as a checkbox.