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 相关文章推荐
解决jquery .ajax 在IE下卡死问题的解决方法
Oct 26 Javascript
javascript感应鼠标图片透明度显示的方法
Feb 24 Javascript
分享十五款 jQuery 社交网络分享插件
May 16 Javascript
jQuery+ajax实现实用的点赞插件代码
Jul 06 Javascript
浅谈javascript中的三种弹窗
Oct 21 Javascript
JS常用算法实现代码
Nov 14 Javascript
Linux使用Node.js建立访问静态网页的服务实例详解
Mar 21 Javascript
Node.js Mongodb 密码特殊字符 @的解决方法
Apr 11 Javascript
Vue2.0 多 Tab切换组件的封装实例
Jul 28 Javascript
jQuery实现鼠标滑过商品小图片上显示对应大图片功能【测试可用】
Apr 27 jQuery
jquery实现动态添加附件功能
Oct 23 jQuery
后台使用freeMarker和前端使用vue的方法及遇到的问题
Jun 13 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如何使用Memcached
2016/04/05 PHP
IE8对JS通过属性和数组遍历解析不一样的地方探讨
2013/05/06 Javascript
基于JavaScript实现继承机制之构造函数方法对象冒充的使用详解
2013/05/07 Javascript
多个jQuery版本共存的处理方案
2015/03/17 Javascript
javascript实现简单的ajax封装示例
2016/12/28 Javascript
微信小程序 同步请求授权的详解
2017/08/04 Javascript
bootstrap-table组合表头的实现方法
2017/09/07 Javascript
如何在Angular8.0下使用ngx-translate进行国际化配置
2019/07/24 Javascript
超轻量级的js时间库miment使用解析
2019/08/02 Javascript
微信JSSDK实现打开摄像头拍照再将相片保存到服务器
2019/11/15 Javascript
Vue解析剪切板图片并实现发送功能
2020/02/04 Javascript
JS删除对象中某一属性案例详解
2020/09/08 Javascript
python局域网ip扫描示例分享
2014/04/03 Python
Python实现Tab自动补全和历史命令管理的方法
2015/03/12 Python
在Python的Django框架中调用方法和处理无效变量
2015/07/15 Python
Python嵌套列表转一维的方法(压平嵌套列表)
2018/07/03 Python
用pycharm开发django项目示例代码
2019/06/13 Python
PyQt5响应回车事件的方法
2019/06/25 Python
用python3读取python2的pickle数据方式
2019/12/25 Python
基于Python计算圆周率pi代码实例
2020/03/25 Python
Python分类测试代码实例汇总
2020/07/23 Python
python通过函数名调用函数的几种场景
2020/09/23 Python
详解pycharm配置python解释器的问题
2020/10/15 Python
车间调度岗位职责
2013/11/30 职场文书
销售部主管岗位职责
2013/12/18 职场文书
面包店的创业计划书范文
2014/01/16 职场文书
临床护士自荐信
2014/01/31 职场文书
志愿者活动总结报告
2014/06/27 职场文书
树转促学习心得体会
2014/09/10 职场文书
群众路线教育实践活动思想汇报(2014特荐篇)
2014/09/16 职场文书
股东出资证明书(正规版)
2014/09/24 职场文书
党的群众路线教育实践活动对照检查材料思想汇报(党员篇)
2014/09/25 职场文书
党的群众路线对照检查材料思想汇报
2014/09/25 职场文书
单位婚育证明范本
2014/11/21 职场文书
幼儿教师个人总结
2015/02/05 职场文书
MySQL批量更新不同表中的数据
2022/05/11 MySQL