有兴趣的可以在 ie ff 中分别执行这段代码 :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>setXY bug</title>
<!--
<script type="text/javascript" src="ext-base.js"></script>
<script type="text/javascript" src="ext-core.js"></script>
-->
<script type="text/javascript" src="ext-core-3.0.js"></script>
</head>
<body>
<div id="test1" style="position:relative;width:100px;height:100px;border:1px solid green;
padding:20px;">
<div id="test2" style="position:absolute;width:50px;height:50px;margin:10px;
border:1px solid red;">
</div>
</div>
<script type="text/javascript">
//<![CDATA[
Ext.onReady(function(){
alert("getBoundingClientRect of test2 : "+
document.getElementById('test2').getBoundingClientRect().left);
alert("offsetLeft of test2 : "+document.getElementById('test2').offsetLeft);
alert("getBoundingClientRect of test2's parent : "+
document.getElementById('test1').getBoundingClientRect().left);
Ext.get('test2').setX(Ext.get('test2').getX());
//if fixed by myself
//Ext.get('test2').setX(Ext.get('test2').getX() -
//parseInt(Ext.get('test2').getStyle("margin-left"),10));
alert("after current getBoundingClientRect of test2 : "+
document.getElementById('test2').getBoundingClientRect().left);
});
//]]>
</script>
</body>
</html>
将得到的页面坐标再设置回去,ie元素位置却改变了。
分析:
在以前的文章 也分析过,由于 ie 不能取得运行时的未显式设置的 left 值,于是 extjs 用offsetLeft 变通了一下,可是毕竟 offsetleft 和 left 还是不一样的 。
left 可能都比较熟悉了,有一点注意: css 2.1 规定偏移是以外边距边界而不是以内容边界。
关于 offsetleft
在元素 A 上读取 offsetLeft 属性时,必须按以下算法返回结果值:
1. 如果元素 A 是 HTML 的 body 元素,其 display 属性计算值是 none,或者不具有 CSS 布局盒子,则返回 0,并停止本算法。
2. 如果元素 A 的 offsetParent 是 null 或者是 HTML 的 body 元素,以 CSS 像素为单位返回元素 A 左边框距画布原点的水平距离,并停止本算法。
3. 以 CSS 像素为单位返回元素 A 左 border edge 距其 offsetParent 左 padding edge 的距离。关于 border edge 与 padding edge 可见 css2.1 的相关定义 。
为了更好地理解,可以参照下图:
上图中,大块是小块的 offsetParent,红色是大块的边框,蓝色是小块的边框,蓝框外白色区域是大块的 padding 或/和 小块的 margin 或其他元素或其他原因造成的空白。offsetTop 是小块上边框上部与大块上边框下部的距离;offsetLeft 是小块左边框左部与大块左边框右部的距离。
则可见在例子中情况下 offsetLeft = left + margin-left
所以精确需要的话改动一下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>setXY bug</title>
<script type="text/javascript" src="ext-base.js"></script>
<script type="text/javascript" src="ext-core.js"></script>
<!--
<script type="text/javascript" src="ext-core-3.0.js"></script>
-->
</head>
<body>
<div id="test1" style="position:relative;width:100px;height:100px;
border:1px solid green;padding:20px;">
<div id="test2" style="position:absolute;width:50px;height:50px;
margin:10px;border:1px solid red;">
</div>
</div>
<script type="text/javascript">
//<![CDATA[
Ext.onReady(function(){
alert("getBoundingClientRect of test2 : "+
document.getElementById('test2').getBoundingClientRect().left);
alert("offsetLeft of test2 : "+document.getElementById('test2').offsetLeft);
alert("getBoundingClientRect of test2's parent : "+
document.getElementById('test1').getBoundingClientRect().left);
if(!isNaN(parseInt(Ext.get('test2').getStyle("left"))))
Ext.get('test2').setX(Ext.get('test2').getX());
else
Ext.get('test2').setX(Ext.get('test2').getX() -
parseInt(Ext.get('test2').getStyle("margin-left"),10));
alert("after current getBoundingClientRect of test2 : "+
document.getElementById('test2').getBoundingClientRect().left);
});
//]]>
</script>
</body>
</html>
PS:
其实对于任何不能得到精确用户未设置left数值的浏览器都存在ie中的情况。(现代的标准浏览器可以避免),进一步发散来讲,这就涉及了 ie 下取得css属性像素值的问题 。另外还有
关于 setXY 的一点剖析 ,特别对于以html为包含块的情况。
已提交 extjs 官方bug报告。