js 弹出菜单/窗口效果


Posted in Javascript onOctober 30, 2011

是不是应该为弹出菜单提供更好的可访问支持?这篇文章将涉及到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,虽然只是没有特别优化的一段代码,但相信可以解决很多问题。对于可访问性,我们要走的路还有很多。一点点来吧,从今天开始。
Javascript 相关文章推荐
Prototype Date对象 学习
Jul 12 Javascript
onsubmit阻止form表单提交与onclick的相关操作
Sep 03 Javascript
jQuery过滤选择器详解
Jan 13 Javascript
EditPlus 正则表达式 实战(3)
Dec 15 Javascript
详解AngularJs HTTP响应拦截器实现登陆、权限校验
Apr 11 Javascript
详解Node.js项目APM监控之New Relic
May 12 Javascript
js 获取html5的data属性实现方法
Jul 28 Javascript
JavaScript获取移动设备型号的实现代码(JS获取手机型号和系统)
Mar 10 Javascript
Auto.js自动收取自己和好友蚂蚁森林能量脚本
Jun 28 Javascript
layui清除radio的选中状态实例
Nov 14 Javascript
jQuery HTML设置内容和属性操作实例分析
May 20 jQuery
实例分析javascript中的异步
Jun 02 Javascript
基于Jquery+Ajax+Json的高效分页实现代码
Oct 29 #Javascript
简单的前端js+ajax 购物车框架(入门篇)
Oct 29 #Javascript
分享一个自己写的table表格排序js插件(高效简洁)
Oct 29 #Javascript
Json2Template.js 基于jquery的插件 绑定JavaScript对象到Html模板中
Oct 29 #Javascript
基于jQuery的输入框在光标位置插入内容, 并选中
Oct 29 #Javascript
基于jquery的无限级联下拉框js插件
Oct 29 #Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
Oct 29 #Javascript
You might like
谈谈PHP语法(5)
2006/10/09 PHP
使用ob系列函数实现PHP网站页面静态化
2014/08/13 PHP
19个Android常用工具类汇总
2014/12/30 PHP
ThinkPHP使用Smarty第三方插件方法小结
2016/03/19 PHP
Js动态创建div
2008/09/25 Javascript
表单JS弹出填写提示效果代码
2011/04/16 Javascript
JS实现新浪博客左侧的Blog管理菜单效果代码
2015/10/22 Javascript
EasyUI在表单提交之前进行验证的实例代码
2016/06/24 Javascript
JS获取中文拼音首字母并通过拼音首字母快速查找页面内对应中文内容的方法【附demo源码】
2016/08/19 Javascript
jQuery is not defined 错误原因与解决方法小结
2017/03/19 Javascript
vue中的scope使用详解
2017/10/29 Javascript
js与jQuery实现的用户注册协议倒计时功能实例【三种方法】
2017/11/09 jQuery
vue代理和跨域问题的解决
2018/07/18 Javascript
vue 刷新之后 嵌套路由不变 重新渲染页面的方法
2018/09/13 Javascript
微信小程序自定义带价格显示日历效果
2018/12/29 Javascript
JavaScript设计模式之观察者模式实例详解
2019/01/16 Javascript
Vue Object.defineProperty及ProxyVue实现双向数据绑定
2020/09/02 Javascript
[00:10]DOTA2全国高校联赛速递
2018/05/30 DOTA
Python模块学习 filecmp 文件比较
2012/08/27 Python
python中使用smtplib和email模块发送邮件实例
2014/04/22 Python
python实现的简单猜数字游戏
2015/04/04 Python
Python线程详解
2015/06/24 Python
Python多线程实现同步的四种方式
2017/05/02 Python
运用TensorFlow进行简单实现线性回归、梯度下降示例
2018/03/05 Python
tensorflow获取变量维度信息
2018/03/10 Python
Python OpenCV读取png图像转成jpg图像存储的方法
2018/10/28 Python
使用python将图片按标签分入不同文件夹的方法
2018/12/08 Python
利用Python实现微信找房机器人实例教程
2019/03/10 Python
python利用Excel读取和存储测试数据完成接口自动化教程
2020/04/30 Python
荷兰之家英文站:Holland at Home
2016/10/26 全球购物
销售总监岗位职责
2014/01/04 职场文书
护士的自我鉴定
2014/02/07 职场文书
会计电算化专业求职信
2014/06/10 职场文书
土建施工员岗位职责
2014/07/16 职场文书
社保代办委托书怎么写
2014/10/06 职场文书
Python操作CSV格式文件的方法大全
2021/07/15 Python