因工作关系我已有些时日没用 YUI 写代码了,
这次由于项目需要我阅读了一些脚本库的代码,
无意间发现了这个 YUI 里 (Dom || Node).getXY() 的小 Bug。
查看了手边的 YUI 2 和 3 的多个版本代码,
均存在此问题。(怀疑其影响全系列)
时间不多,
抽睡前的一点时间写下来吧。

问题描述如下:
当浏览器不支持 node.getBoundingClientRect() 方法时,
我们会选择通过 offset 系列属性一层层向上计算偏移值,
最后得到一个“可能有错误的”元素坐标。
要修正这个错误,
我们需要沿着节点树一层层向上判断是否某个祖先“出现”了滚动条,
如果有,对不起,阉了。

大体的思路是这样没错,
YUI 也确实这样处理了,
而且它也知道元素定位方式中还有一种游离于布局之外的 fixed,
只可惜它没在碰到 fixed 元素时及时刹车,
结果就是在一种较特殊的布局下会多删一次滚动条高/宽度,
导致坐标计算错误。
可叹可叹,
它曾那么接近幸福。

所以当某个有滚动条的页面里存在一个 fixed 定位的元素,
而你又要用 YUI 去取该元素所包含的某个子元素的坐标时,
Bug 就出现了。
文字描述显然不够直观,
请猛击如下链接来查看不才基于 YUI2YUI3 所构建的示例。
(由于该 Bug 只影响不支持 node.getBoundingClientRect() 的浏览器,
请选用诸如 Firefox 2 / Chrome 1 / Safari 3 等浏览器来打开示例,
顺便在这里感谢 IE 团队为我们贡献了如此好用的一个方法)

在以上示例中,
我先将绿色的层定位到上述布局元素的左上角,
接着模拟浏览器发生滚动,
然后再次将绿色的层移动到该元素左上角,
如果第二次没有被正确地定位过去则问题被触发。

要修正该问题也非常简单,
下面以 YUI 2.8.0r4 为例进行修正:

打开 dom/dom.js ,
找到如下代码:

if (scrollTop || scrollLeft) { xy[0] -= scrollLeft; xy[1] -= scrollTop; }

在其下方增加:

// jump out when there's a fixed-position parent // by Chappell.Wat from QuChao.com if (Y.Dom._getStyle(parentNode, POSITION) === FIXED) { break; }

如果你懒得可以,
可以直接下载我修正好的 dom.js ⇓ ,
点此查看修正后的结果

P.S.
jQuery 不存在此问题,
可以点此查看我的示例
其它脚本库尚未测试。

好了,
明早起来看看是否需要给 YUI 提个 Bug 单

标签: JavaScript, Bugfix, YUI

已有 4 条评论

  1. Abercrombie and Fitch Abercrombie and Fitch

      善于下命令的人,必定能够服从命令并且执行。

  2. 任鸟飞 任鸟飞

    技术贴,太技术了,一时看的不太懂啊,看来得慢慢研究一下。

  3. 后

    加我QQ吧 有问题请教大哥

  4. 高清电影网 高清电影网

    果然神啊!谢谢分享

添加新评论