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 相关文章推荐
引用 js在IE与FF之间的区别详细解析
Nov 20 Javascript
JavaScript的History API使搜索引擎抓取AJAX内容
Dec 07 Javascript
学习JavaScript事件流和事件处理程序
Jan 25 Javascript
js友好的时间返回函数
Aug 24 Javascript
Javascript 6里的4个新语法
Aug 25 Javascript
如何正确理解javascript的模块化
Mar 02 Javascript
浅析Vue中method与computed的区别
Mar 06 Javascript
ES6知识点整理之数组解构和字符串解构的应用示例
Apr 17 Javascript
vue中input的v-model清空操作
Sep 06 Javascript
Vue实现push数组并删除的例子
Nov 01 Javascript
d3.js 地铁轨道交通项目实战
Nov 27 Javascript
jQuery+css实现的点击图片放大缩小预览功能示例【图片预览 查看大图】
May 29 jQuery
基于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命名空间与自动加载类详解
2018/09/04 PHP
PHP连续签到功能实现方法详解
2019/12/04 PHP
JavaScript For Beginners(转载)
2007/01/05 Javascript
JS 显示当前日期与时间的代码
2010/03/24 Javascript
JavaScript中通过闭包解决只能取得包含函数中任何变量最后一个值的问题
2010/08/12 Javascript
javascript常用方法、属性集合及NodeList 和 HTMLCollection 的浏览器差异
2010/12/25 Javascript
js 限制input只能输入数字、字母和汉字等等
2013/12/18 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
举例讲解Node.js中的Writable对象
2015/07/29 Javascript
jQuery实现点击后高亮背景固定显示的菜单效果【附demo源码下载】
2016/09/21 Javascript
javascript数组去重方法分析
2016/12/15 Javascript
详解vue中引入stylus及报错解决方法
2017/09/22 Javascript
详解Vue 事件修饰符capture 的使用
2017/12/29 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
详解Vue组件之间通信的七种方式
2019/04/14 Javascript
jQuery实现高度灵活的表单验证功能示例【无UI】
2020/04/30 jQuery
vue自定义组件实现双向绑定
2021/01/13 Vue.js
python获取局域网占带宽最大3个ip的方法
2015/07/09 Python
Python读写docx文件的方法
2018/05/08 Python
Python使用matplotlib实现基础绘图功能示例
2018/07/03 Python
python中使用zip函数出现错误的原因
2018/09/28 Python
使用50行Python代码从零开始实现一个AI平衡小游戏
2018/11/21 Python
python 批量解压压缩文件的实例代码
2019/06/27 Python
解决在pycharm运行代码,调用CMD窗口的命令运行显示乱码问题
2019/08/23 Python
Python中注释(多行注释和单行注释)的用法实例
2019/08/28 Python
scrapy在python爬虫中搭建出错的解决方法
2020/11/22 Python
澳大利亚婴儿喂养品牌:Cherub Baby
2018/11/01 全球购物
在加拿大在线租赁和购买电子游戏:Game Access
2019/09/02 全球购物
升职自荐信范文
2013/10/05 职场文书
历史教育专业个人求职信
2013/12/13 职场文书
小学教师培训方案
2014/06/09 职场文书
新郎父母婚礼致辞
2015/07/27 职场文书
家庭教育教师培训学习体会
2016/01/14 职场文书
励志语录:只有自己足够强大,才能不被别人践踏
2020/01/09 职场文书
CPU不支持Windows11系统怎么办
2021/11/21 数码科技
动画电影《龙珠超 超级英雄》延期上映
2022/03/20 日漫