Whatever:hover 无需javascript让IE支持丰富伪类


Posted in Javascript onJune 29, 2010

这很酷,因为这使你可以仅通过 css来对表格行(<tr>)应用鼠标滑过事件(mouseover)时的特殊效果。然而,万恶的IE,对 :hover伪类顶多只提供了有限的支持,具体支持的程度要取决于你的IE浏览器的具体版本。

Whatever:hover 是一个小小的脚本,它可以迅速、自动地为IE6,IE7,IE8添加标准的 :hover、:active 和:focus 伪类支持。第三版引入了 ajax 支持,意味着通过 javascript动态添加到文档中的任意html元素也同样可以在IE中响应 :hover、:active 和 :focus 样式。

 

如果你已经对使用 whatever:hover 很熟练,现在只是想下载它,你可以直接跳转到获取最新版本。而对于其它想深入了解它的人,请继续阅读。

使用方法

你只需要将 whatever:hover 链接到 body 元素就可以了。注意这里的 behavior 属性中的 URL 是相对于 html 文件的,而不是像背景图片地址一样是相对于 css 文件的路径。

body { behavior: url("csshover3.htc"); }

工作原理

所有的浏览器都提供了一些方法,让你用 javascript 查询样式表中定义好的规则或者动态地插入新规则。正常情况下,IE对所有它不支持的规则返回 “unknown”。例如:一条关于 “div p:first-child” 的规则将会被改成 "divp:unknown”, 而一条关于 "p a[href]” 的规则将整体地作为 "unknown" 返回。幸运的是 IE 把 :hover伪类认为是它支持的样式规则,并且会将它保持原样。

IE 还支持所谓的行为(behaviors),不仅包括预定义的功能比如动态加载内容或者持续数据存储,也包括你可以在一个后缀为 .htc 或者 .hta 为的文件中创建的自定义行为。这些行为通过 css 实现与 html 节点关联,并“增强”这些被指定行为中的样式选择器选中的节点。

综上所述,创建一个行为来查找样式表中 IE 不支持的元素,并以一些其它手段“欺骗”影响的到元素让它们应用样式表中关联的样式。这个复杂的操作中包含的步骤大致可以描述为:

  • 在所有的样式表中搜索 IE 不支持的 :hover 伪类规则;
  • 插入一条 IE 支持的,例如带 class 名称的新规则;
  • 最后,设置脚本事件来切换目标元素的 class 名称。

通过这种方式,:hover、:active 和 :focus 就可以得到(IE 的)支持了。而作为开发人员,你除了包含这个行为以外不需要做任何事。所有的工作都将自动完成。

与第1版和第2版比较,第3版对动态加入的 html (ajax) 也同样支持。另外还有一个改动是原来第1版和第2版采用的是在页面加载事件中主动搜索影响到的元素,而在第3版中改为借助表达式(expressions)让节点自己回调。关于这部分你可以阅读带注释的版本获取更多细节。

示例:菜单效果

:hover 一个很常见的用途就是用列表创建菜单系统。用这个行为来创建一个两级的菜单系统是再容易不过的事情了。例如,如果你从 suckerfish dropdown (一个带有下拉菜单的网页,关于这个页面和效果的描述,参见 A List Apart article)上把 javascript 删除掉了,它仍然能正常工作。

但是多级的菜单需要做不同的处理。这是由于 IE 不支持子选择符 ‘>',子选择符可以完美地显示下级子菜单,而不是连更深层的菜单一起显示出来。

li:hover > ul { /* 在 IE 下无效 */ }

有一种可供选择的方法可以只使用简单的子孙选择符来模拟这种行为(主要是针对 IE)。还有种不太成熟的方法是应用多个类定义,但是更简单的方法是利用 CSS 选择符的不同优先级(specificity).每一条 css 规则都有特定的重要等级,这个等级可以简单地根据一条规则中的不同元素来计算。以元素名称为基准值 “1″,类、伪类和属性选择符重要性(权重)为 “10″,然后元素 id 为 “100″。比如下面的例子。

ul ul { display:none; }
li:hover ul { display:block; }

这样做能够生效的原因,就是选择符的优先级不同。第一条规则只包含两个元素名称,这样它的权重值(优先级)就是2。第二条规则也包含两个元素名称,但是 :hover 伪类的权重值(优先级)是10,所以加起来的值就是12。由于第二条规则比第一条规则优先,因此被鼠标滑过的 li 元素内部的ul 将被显示。

那么这个对于解决 >子选择符的问题有什么帮助呢?是这样,如果一条权重值(优先级)为12的规则定义所有的子菜单都要显示,我们只需要创建一条权重值(优先级)大于12的规则来把下一级的菜单隐藏起来。然后,那个菜单又需要另一条优先级更高的规则来显示,一直循环下去。对于3级的导航来说,需要的 css代码短得让人意外:

/* 2 和 13 */
ul ul, li:hover ul ul { display:none; }
/* 12 和 23*/
li:hover ul, li:hover li:hover ul { display:block; }

这种方式可以无需附加任何类样式实现无限级嵌套菜单(4级或更多级需要需要继续添加更多规则)。

脚本事件的性能优化

现在还剩下一件事需要考虑。.htc 文件在所有样式表文件中搜索 :hover 规则,并且按照 css 文件的定义对所有它认为需要用脚本处理停留效果的元素附加鼠标滑过和移出事件。为了找出这些(被影响的)元素,所有去掉 :hover 伪类选择到的元素以及被 :hover 伪类修饰的元素本身,都会被选择并且进行处理。一条类似这样的规则

#menu li:hover ul { ... }

…将会被调整成下面这样来查找所有可能需要响应鼠标滑过事件的元素:

#menu li { ... }

很显然这会选中整个菜单中的每一个 <li>元素,并对其中一大堆不需要鼠标事件(在当前情况下)的元素附加事件。这个问题可以很轻松地得到解决,我们可以对包含子菜单的列表元素添加一个类样式,比如 "folder"。这样一来,调整(去除:hover)之后的样式规则变成了

#menu li.folder { ... }

…可以高效地直接选中那些真正需要事件的元素。缺点是为了改善脚本的性能,你需要添加一个类样式(这个类样式的添加纯粹是为了视觉效果,而且放弃了li:hover 方式实现菜单的通用性)。但是,从另一个角度考虑的话,也许你反正也要用一个类来把这些列表元素与普通元素区别开来,那就无所谓了。

为了直观地说明上述问题,请查看综合示例。希望你喜欢。

文件下载及更新说明:

Javascript 相关文章推荐
javascript 学习之旅 (3)
Feb 05 Javascript
解析js原生方法创建表格效率测试
Jul 08 Javascript
jQuery的each终止或跳过示例代码
Dec 12 Javascript
解决ueditor jquery javascript 取值问题
Dec 30 Javascript
javascript实现了照片拖拽点击置顶的照片墙代码
Apr 03 Javascript
jQuery实现仿百度帖吧头部固定导航效果
Aug 07 Javascript
Jquery跨浏览器文本复制插件Zero Clipboard的使用方法
Feb 28 Javascript
jQuery实现智能判断固定导航条或侧边栏的方法
Sep 04 Javascript
bootstrap日历插件datetimepicker使用方法
Dec 14 Javascript
基于Vue插入视频的2种方法小结
Apr 02 Javascript
vue指令做滚动加载和监听等
May 26 Javascript
解决VUE自定义拖拽指令时 onmouseup 与 click事件冲突问题
Jul 24 Javascript
javascript hasFocus使用实例
Jun 29 #Javascript
jquery photoFrame 图片边框美化显示插件
Jun 28 #Javascript
使用jQuery.Validate进行客户端验证(初级篇) 不使用微软验证控件的理由
Jun 28 #Javascript
jquery获取ASP.NET服务器端控件dropdownlist和radiobuttonlist生成客户端HTML标签后的value和text值
Jun 28 #Javascript
Jquery ui css framework
Jun 28 #Javascript
Javascript创建Silverlight Plugin以及自定义nonSilverlight和lowSilverlight样式
Jun 28 #Javascript
JavaScript Tips 使用DocumentFragment加快DOM渲染速度
Jun 28 #Javascript
You might like
PHP脚本的10个技巧(5)
2006/10/09 PHP
PHP中的日期及时间
2006/11/23 PHP
php之字符串变相相减的代码
2007/03/19 PHP
ThinkPHP在新浪SAE平台的部署实例
2014/10/31 PHP
php微信公众平台开发(四)回复功能开发
2016/12/06 PHP
微信公众号开发之通过接口删除菜单
2017/02/20 PHP
谈谈从phpinfo中能获取哪些值得注意的信息
2017/03/28 PHP
js 页面传参数时 参数值含特殊字符的问题
2009/12/13 Javascript
javascript 自动填写表单的实现方法
2010/04/09 Javascript
ExtJS PropertyGrid中使用Combobox选择值问题
2010/06/13 Javascript
jQuery父级以及同级元素查找介绍
2013/09/04 Javascript
js的for in循环和java里foreach循环的区别分析
2015/01/28 Javascript
JS实现仿QQ效果的三级竖向菜单
2015/09/25 Javascript
jQuery-1.9.1源码分析系列(十)事件系统之事件包装
2015/11/20 Javascript
Node.js文件操作方法汇总
2016/03/22 Javascript
原生JS实现旋转木马式图片轮播插件
2016/04/25 Javascript
jQuery中hover方法搭配css的hover选择器,实现选中元素突出显示方法
2017/05/08 jQuery
Cocos2d实现刮刮卡效果
2018/12/20 Javascript
JS实现二维数组元素的排列组合运算简单示例
2019/01/28 Javascript
Vue 子组件与数据传递问题及注意事项
2019/07/11 Javascript
vue从一个页面跳转到另一个页面并携带参数的解决方法
2019/08/12 Javascript
jQuery实现简易聊天框
2020/02/08 jQuery
Python读取mat文件,并保存为pickle格式的方法
2018/10/23 Python
python如何获取列表中每个元素的下标位置
2019/07/01 Python
使用Python轻松完成垃圾分类(基于图像识别)
2019/07/09 Python
python3获取文件中url内容并下载代码实例
2019/12/27 Python
Python自定义聚合函数merge与transform区别详解
2020/05/26 Python
在pytorch中动态调整优化器的学习率方式
2020/06/24 Python
Python 利用Entrez库筛选下载PubMed文献摘要的示例
2020/11/24 Python
TripAdvisor越南:全球领先的旅游网站
2017/09/21 全球购物
销售行政专员职责
2014/01/03 职场文书
各营销点岗位职责范本
2014/03/05 职场文书
农民工工资支付承诺函
2014/03/31 职场文书
班主任经验交流会主持词
2014/04/01 职场文书
JavaScript如何优化逻辑判断代码详解
2021/06/08 Javascript
SQL使用复合索引实现数据库查询的优化
2022/05/25 SQL Server