javascript - Simulate Voiceover page load in single-page pushState web application -
i'm working on single-page application (spa) we're simulating multi-page application html 5 history.pushstate
. looks fine visually, it's not behaving correctly in ios voiceover. (i assume wouldn't work in screen reader, voiceover i'm trying first.)
here's example of behavior i'm trying achieve. here 2 ordinary web pages:
1.html
<!doctype html><html> <body>this page 1. <a href=2.html>click here page 2.</a></body> </html>
2.html
<!doctype html><html> <body>this page 2. <a href=1.html>click here page 1.</a></body> </html>
nice , simple. voiceover reads this:
web page loaded. page 1.
[swipe right] click here page 2. link.
[double tap] web page loaded. page 2.
[swipe right] click here page 1. visited. link.
[double tap] web page loaded. page 1.
here again single-page application, using history manipulation simulate actual page loads.
spa1.html
<!doctype html><html> <body>this page 1. <a href='spa2.html'>click here page 2.</a></body> <script src="switchpage.js"></script> </html>
spa2.html
<!doctype html><html> <body>this page 2. <a href='spa1.html'>click here page 1.</a></body> <script src="switchpage.js"></script> </html>
switchpage.js
console.log("load"); attachhandler(); function attachhandler() { document.queryselector('a').onclick = function(event) { event.preventdefault(); history.pushstate(null, null, this.href); drawpage(); } } function drawpage() { var page, otherpage; // in real life, we'd ajax call here or if (/spa1.html$/.test(window.location.pathname)) { page = 1; otherpage = 2; } else { page = 2; otherpage = 1; } document.body.innerhtml = "this page " + page + ".\n<a href='spa"+otherpage+".html'>click here page " + otherpage + ".</a>"; attachhandler(); } window.onpopstate = function() { drawpage(); };
(note sample doesn't work filesystem; have load webserver.)
this spa example visually looks simple multi-page example, except page 2 "loads quicker" (because it's not loading @ all; it's happening in js).
but in voiceover, doesn't right thing.
web page loaded. page 1.
[swipe right] click here page 2. link.
[double tap] click here page 1. visited. link.
[the focus on link! swipe left] page 2.
[swipe right] click here page 1. visited. link.
[double tap] web page loaded. page 1.
the focus on link, when should @ top of page.
how tell voiceover whole page has updated , reader should resume reading top of page?
jorgen's answer, based on another stackoverflow thread got me on right track.
the actual fix not wrap entire page in <div tabindex=-1>
instead create <span tabindex=-1>
around first part ("this page n") , focus that.
function drawpage() { var page, otherpage; // in real life, we'd ajax call here or if (/spa1.html$/.test(window.location.pathname)) { page = 1; otherpage = 2; } else { page = 2; otherpage = 1; } document.body.innerhtml = '<span tabindex="-1" id="page' + page + '">this page ' + page + '.</span>\n<a href="spa'+otherpage+'.html">click here page ' + otherpage + '.</a>'; document.getelementbyid('page' + page).focus(); settimeout(function() { document.getelementbyid('page' + page).blur(); }, 0); attachhandler(); }
note in example blur focus in timeout; otherwise, non-screen-reader browsers draw visible blue focus rectangle around span, not want. blurring focus doesn't affect focus of ios vo reader.
Comments
Post a Comment