Hello all,
I would appreciate your help in the following matter. I encountered a situation in an iOS app where I need to move the VoiceOver cursor to a specific HTML element (a specific heading) inside a UIWebView.
The situation in the app is that there is table of contents displayed in a separate view ("TOC view"). When the user selects an item in the table of contents, the TOC view is dismissed, the webView scrolls visually to the selected position and VoiceOver cursor moves to the beginning of the screen (the navbar back button). Therefore, when the blind user tries to enter the webView again by flicking right, the webView scrolls to the very beginning and the VoiceOver cursor is placed on the first element in the webpage. Therefore, the selection made in the table of contents is lost and therefore the table of contents is useless. What we need instead is to move the VoiceOver cursor to the corresponding HTML element inside the UIWebView when an item is selected in the TOC view and the TOC view is dismissed.
The problem I face is twofold:
1) How to move the VoiceOver cursor to a specific HTML element inside a UIWebView? 2) How to prevent other events (related to the TOC view dismissal) to subsequently steal the cursor?
Below, I will try to describe what I have tried so far.
Regarding the first question (how to set the cursor), I have been experimenting with calling the _javascript_ focus() method on the HTML element (after first setting its tabindex to 0). This seems to work with the drawback that it doesn’t work while performed twice in a row, because calling focus() on an element that already has the focus does not seem to do anything with the VoiceOver cursor. So in fact what is necessary is to first set focus() to some other element, then set it to the desired element. Also, it seems a little strange to me that calling focus() in a _javascript_ inside the UIWebView brings the VoiceOver cursor to it even if some other view (not the UIWebView) was originally focused and I am not sure if it is possible to rely on such a behavior for the future. I would appreciate any input of whether this method using _javascript_ is correct or if there is some better way?
Regarding the second question (how to prevent other events from stealing the cursor), I thought that setting the cursor to the UIWebView explicitly via UIAccessibilityScreenChangedNotification with the UIWebView as a parameter should do the job. I was expecting that the UIWebView will accept the cursor and place it at to the point set internally via the _javascript_ focus() method. However, when the VoiceOver focus is passed to the UIWebView via this notification, the UIWebView sets the VoiceOver cursor to the first HTML element in the view (not the current focus position).
I have also tried calling UIAccessibilityScreenChangedNotification with the nil parameter. This seems to always reset the focus to the beginning of screen (a back button in the navigation bar in my case) even if the UIWebView already had focus, which looks counter-intuitive to me. An internal event of this type seems to be the reason why the VoiceOver cursor is stolen from the WebView in my case.
I have also tested this in a minimal situation with a WKWebView instead of the UIWebView and it looks the behavior is very similar, except the call of UIAccessibilityScreenChangedNotification with the UIWebView as a parameter seems to set the VoiceOver cursor at the geometric middle of the view rather than to the beginning of the view.
I would be very thankful for any advice on this issue :-)
Thank you very much, Hynek
|