js 弹出菜单/窗口效果

所属分类: 网络编程 / JavaScript 阅读数: 979
收藏 0 赞 0 分享
是不是应该为弹出菜单提供更好的可访问支持?这篇文章将涉及到3种常见的弹窗:

window.open 新建的浏览器窗口
<iframe /> 创建的窗口
页面 DOM 创建的伪弹出窗口:如弹出 tips 等

一、当页面无 JS 的时候
通常来说,无 JS 的情况那就按 HTML 的行为来做事。让链接可以链接,就已经解决。比较简单,我们简单带过:

1. window.open 新建的浏览器窗口:尽量让 JS 触发器绑定在 <a /> 上,并把 a 链接到一个新的页面,即可。
复制代码 代码如下:

// 链接与 window.open 的目标相同
<a href="/target.html" target="_blank">[open window]</a>
// 记得阻止链接有默认行为,不然有 JS 的时候会打开两次
window.open('./iframe.html', 'name', 'height=300,width=500');
return false;

2. <iframe /> 创建的窗口:如果是用 JS 动态创建的,那么记得触发器也应该像 window.open 的方法一样,把解法链接写在一个 <a /> 上,让用户通过链接来访问。而如果是隐藏的,那么尽量来使用 <noscript /> 来隐藏,再用 JS 让其正常显示出来;或者高度为 0 的空 iframe 。这样即可保证在有 JS 的时候可用,而在无 JS 的时候可以正常显示。详细应用可以参照:支付宝新首页的几点前端实践。
复制代码 代码如下:

// 动态创建,请尽量使用这种方法,因为 IE8 不能用 JS focus 到动态创建的 focusable 元素
// 而空 src 则请使用 javascript:'' 这种方式,因为这是解决性能的最好方式,详见:空路径对页面性能影响的解决方案

<a href="/target.html" target="_blank">[open iframe]</a>
<iframe src="javascript:''" frameborder=0 id="theframe"></iframe>
// js
document.getElementById('theframe').src = '/target.html'

3. 页面 DOM 创建的伪弹出窗口:使用 <noscript /> 来隐藏。链接用锚点。
复制代码 代码如下:

<a href="#target">[open current page DOM]</a>
... 很多很多东西隔在中间 ...
<noscript><div id="target">content</div></noscript>

二、大多数情况下
大数多情况下,用户的浏览器都是有开启 JS 的。而我们要做的是:focus 到弹出的窗口,并且第一个 tab 就可以访问里面的内容。听过来挺简单的,hub? 先看看 DEMO:

预览:可访问弹出菜单/窗口

1. window.open 新建的浏览器窗口:focus 到新建的窗口即可。
复制代码 代码如下:

// 引用自:QuickMode - popups
function popitup(url) {
newwindow=window.open(url,'name','height=200,width=150');
if (window.focus) {
// focus 到新建窗口
newwindow.focus();
}
// 阻止触发器的默认行为
return false;
}

2. <iframe /> 创建的窗口:调试了好久,IE8/9 需要等 iframe onload 成功后 setTimeout 来 hack;firefox 不能使用 ifrcontentWindow.focus(),只能用 iframe.focus()。综合起来需要这样的代码:
复制代码 代码如下:

// for all except firefox
setTimeout(function(){
f.contentWindow.focus();
}, 50);

// hack for firefox
navigator.userAgent.toLowerCase().indexOf('firefox') !== -1 && f.focus();

3. 页面 DOM 创建的伪弹出窗口:对于 dom,除了 <a /> <input /> 等这些 focusable 元素(W3C SPEC),都是不可以 focus 的。那么当需要 focus 到一个 div 时,我们有什么方法可以做到呢?通常来说,我们可以设置 Tabindex 来让像 <div /> 这样的非 focusable 元素可以触发 focus 事件。但我们想要的时真正 focus 到一个地方,以便于使用 tab 来访问这个区域的内容,所以这种方法对我们等于无用。

目前还没有比较好的方法(对于我能想到的和找到的),所以目前来说,我们只能利用一个 focusable 元素来创建 focus 目标。我们可以这样做:

<a href="#" class="getfocus">Get focus</a>
<input title="testing" />
但问题是,对于这个链接对于我们来说是毫无作用的,我们需要隐藏他,又能 focus 到。但 display:none 的时候是不能 focus 的。对于隐藏 来说,这里也不想说太多。推荐看看这篇文章:使用clip隐藏内容。那么我们可以这样来 hack 我们的这个链接:
复制代码 代码如下:

// html: 注意用 hidefocus 来删除虚线框
<a href="#" class="getfocus" hidefocus>Get focus</a>

// CSS: 使用 clip
.getfocus{
position:relative;
clip:rect(1px 1px 1px 1px);
clip:rect(1px, 1px, 1px, 1px);
}

// javascript: 记得把 <a /> 放在这个 DOM 结构的最前面方便自上至下 tab 下去
a.focus()

三、总结:
至此,重要的技术实现点也已经说明白。代码请见这个粗陋的 DEMO,虽然只是没有特别优化的一段代码,但相信可以解决很多问题。对于可访问性,我们要走的路还有很多。一点点来吧,从今天开始。
更多精彩内容其他人还在看

jQuery LigerUI 使用教程表格篇(1)

ligerGrid是ligerui系列插件的核心控件,用户可以快速地创建一个美观,而且功能强大的表格,支持排序、分页、多表头、固定列等等
收藏 0 赞 0 分享

JavaScript中常用的运算符小结

JavaScript中常用的运算符小结,需要的朋友可以参考下。
收藏 0 赞 0 分享

深入理解JavaScript系列(13) This? Yes,this!

在这篇文章里,我们将讨论跟执行上下文直接相关的更多细节。讨论的主题就是this关键字。实践证明,这个主题很难,在不同执行上下文中this的确定经常会发生问题
收藏 0 赞 0 分享

javascript (用setTimeout而非setInterval)

javascript (用setTimeout而非setInterval)如果用setInterval 可能出现 下次调用会在前一次调用前调用
收藏 0 赞 0 分享

JavaScript中两个感叹号的作用说明

用两个感叹号的作用就在于,如果明确设置了o中flag的值(非null/undefined/0""/等值),自然test就会取跟o.flag一样的值;如果没有设置,test就会默认为false,而不是null或undefined
收藏 0 赞 0 分享

javascript写的简单的计算器,内容很多,方法实用,推荐

最近用javascript写了一个简单的计算器,自己测试感觉还好,代码都给了注释,非常不错,推荐大家学习。
收藏 0 赞 0 分享

js的表单操作 简单计算器

javascript写的简单的加减乘除计算器,里面涉及到一些方法还是很实用的哦,新手不要错过
收藏 0 赞 0 分享

Jquery中删除元素的实现代码

empty用来删除指定元素的子元素,remove用来删除元素,或者设定细化条件执行删除
收藏 0 赞 0 分享

javaScript 利用闭包模拟对象的私有属性

JavaScript缺少块级作用域,没有private修饰符,但它具有函数作用域。作用域的好处是内部函数可以访问它们的外部函数的参数和变量(除了this和argument
收藏 0 赞 0 分享

为JavaScript类型增加方法的实现代码(增加功能)

大家在js开发过程中有些功能已经满足不了我们的需求,或没有我们需要的功能,那么我们就可以自己扩展下,个性化js
收藏 0 赞 0 分享
查看更多