我正在开发单页应用程序(SPA),我们正在使用HTML 5 history.pushState
模拟多页面应用程序。它在视觉上看起来很好,但在iOS Voiceover中表现不正常。 (我认为它不适用于任何屏幕阅读器,但是我首先尝试使用画外音。)
这是我想要实现的行为的一个例子。这是两个普通的网页:
1.html
<!DOCTYPE html><html>
<body>This is page 1. <a href=2.html>Click here for page 2.</a></body>
</html>
2.html
<!DOCTYPE html><html>
<body>This is page 2. <a href=1.html>Click here for page 1.</a></body>
</html>
美好而简单。画外音如下所示:
已加载网页。这是第1页 [向右滑动]单击此处查看第2页。链接。
[双击]加载网页。这是第2页 [向右滑动]单击此处查看第1页。已访问。链接。
[双击]加载网页。这是第1页。
此处它再次作为单页面应用程序,使用历史记录操作来模拟实际页面加载。
spa1.html
<!DOCTYPE html><html>
<body>This is page 1.
<a href='spa2.html'>Click here for page 2.</a></body>
<script src="switchPage.js"></script>
</html>
spa2.html
<!DOCTYPE html><html>
<body>This is page 2.
<a href='spa1.html'>Click here for 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 do an AJAX call here or something
if (/spa1.html$/.test(window.location.pathname)) {
page = 1;
otherPage = 2;
} else {
page = 2;
otherPage = 1;
}
document.body.innerHTML = "This is page " + page +
".\n<a href='spa"+otherPage+".html'>Click here for page " +
otherPage + ".</a>";
attachHandler();
}
window.onpopstate = function() {
drawPage();
};
(请注意,此示例无法在文件系统中运行;您必须从Web服务器加载它。)
这个SPA示例在视觉上看起来与简单的多页面示例完全相同,只是第2页“加载速度更快”(因为它根本没有真正加载;所有这些都发生在JS中)。
但是在画外音方面,它没有做正确的事。
已加载网页。这是第1页 [向右滑动]单击此处查看第2页。链接。
[双击]点击此处查看第1页。访问。链接。
[重点是链接!向左滑动]这是第2页 [向右滑动]单击此处查看第1页。已访问。链接。
[双击]加载网页。这是第1页。
当焦点位于页面顶部时,焦点在链接上。
如何告诉Voiceover整个页面刚刚更新,读者应该从页面顶部继续阅读?
答案 0 :(得分:1)
another StackOverflow thread让我走上正轨。
实际修复不是将整个页面包裹在<div tabindex=-1>
中,而是围绕第一部分创建<span tabindex=-1>
(“这是页面N”)并将其集中在那里。
function drawPage() {
var page, otherPage;
// in real life, we'd do an AJAX call here or something
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 is page ' + page +
'.</span>\n<a href="spa'+otherPage+'.html">Click here for page ' +
otherPage + '.</a>';
document.getElementById('page' + page).focus();
setTimeout(function() {
document.getElementById('page' + page).blur();
}, 0);
attachHandler();
}
注意在这个例子中我们也模糊了超时的焦点;否则,非屏幕阅读器浏览器会在跨度周围绘制一个可见的蓝色焦点矩形,这不是我们想要的。模糊焦点不会影响iOS VO阅读器的焦点。
答案 1 :(得分:0)
我没有iPhone,但另一个stackoverflow thread提供了解决方案。将内容包装在tabindex为-1的元素中,并以编程方式将焦点设置在该元素上。
function drawPage() {
var page, otherPage;
// in real life, we'd do an AJAX call here or something
if (/spa1.html$/.test(window.location.pathname)) {
page = 1;
otherPage = 2;
} else {
page = 2;
otherPage = 1;
}
document.body.innerHTML = '<div tabindex="-1" id="page' + page + '">This is page ' + page +
'.\n<a href='spa'+otherPage+'.html'>Click here for page ' +
otherPage + '.</a></div>';
document.getElementById('page' + page).focus();
attachHandler();
}