今天在修正一些需求,在使用以往封装好日期htc,发现了一个bug,如下,在正常情况下点击输入框可将隐藏的htc控件能显示在input正下方。
但在滚动层的时候再点击输入框就出现了问题了。
由于blogjava不支持htc上传。所以没演示 : (
有BUG的日历HTC
测试可发现日历控件偏位了。滚动条向下划,它也不断向下偏离input。
查看htc源码。发现其是用getDim(el)函数取得input的X,Y 坐标然后将日历控制定位的。
有bug的取得控件位置的javascript代码
function getDim(el){
for (var lx=0,ly=0;el!=null;
lx+=el.offsetLeft,ly+=el.offsetTop,el=el.offsetParent); // 用offsetLeft , offsetTop 循环累加
return {x:lx,y:ly} //返回 input模式x,y 坐标
} 现在将input 框架放到div 容器中,然而也设置了CSS(position:relative;overflow:auto; )
overflow:auto是指当 内容超出块的情况下,自动显示滚动条
如图分析:
图1是正常没有滚动的情况,
图2、3是滚动后的效果(这两种情况就会出现问题)
原有bug代码
for (var lx=0,ly=0;el!=null;
lx+=el.offsetLeft,ly+=el.offsetTop,el=el.offsetParent); 用offsetParent 中的offsetLeft ,offsetTop 不断累加, 在通常情况下是没有问题的。
但放到容器中,并且有滚动条的情况就会出现问题了。
先来回顾一下dhtml中对象中的几个属性(更多请看DHTL参考书)
offsetParent
------------------------
Retrieves a reference to the container object that defines the offsetTop and offsetLeft properties of the object.
offsetHeight
------------------------
Retrieves the height of the object relative to the layout or coordinate parent,
as specified by the offsetParent property.
offsetLeft
------------------------
Retrieves the calculated left position of the object relative to the layout or coordinate parent,
as specified by the offsetParent property.
offsetParent
------------------------
Retrieves a reference to the container object that defines the offsetTop and offsetLeft properties of the object.
offsetTop
------------------------
Retrieves the calculated top position of the object relative to the layout or coordinate parent, as specified by the offsetParent property.
offsetWidth
------------------------
Retrieves the width of the object relative to the layout or coordinate parent,
as specified by the offsetParent property.
clientHeight
------------------------
Retrieves the height of the object including padding, but not including margin, border, or scroll bar.
clientLeft
------------------------
Retrieves the distance between the offsetLeft property and the true left side of the client area.
clientTop
------------------------
Retrieves the distance between the offsetTop property and the true top of the client area.
clientWidth
------------------------
Retrieves the width of the object including padding, but not including margin, border, or scroll bar.
scrollHeight
------------------------
Retrieves the scrolling height of the object.
scrollLeft
------------------------
Sets or retrieves the distance between the left edge of the object and the leftmost portion of the content currently visible in the window.
scrollTop
------------------------
Sets or retrieves the distance between the top of the object and the topmost portion of the content currently visible in the window.
scrollWidth
------------------------
Retrieves the scrolling width of the object. 显然,原有bug的代码使用
el.offsetTop (取得了当前object相对于其父object的距离),
当div滚动时。
这样计算其真实高度就会有问题(大于其实际的高度)
代码改进,当发现父的tag name 为DIV容器,并设置了相关的style CSS(position:relative;overflow:auto; )
那么我们就不再累加这个
offsetTop,取而代之的公式应该是再减去滚动上去的隐藏了的高度,也就是的值,如上图可清晰发现:
ly = ly + (el.offsetTop - el.scrollTop);修正后取得控件位置的javascript代码,另外左右滚动的相应原理,在这里没写出来
function getDim(el){
for (var lx=0,ly=0;el!=null;
lx+=el.offsetLeft,ly+=el.offsetTop,el=el.offsetParent)
{
if(el.tagName.toLowerCase()=="div" && el.style.position=="relative")
{
ly = ly - el.offsetTop;
ly = ly + (el.offsetTop - el.scrollTop);
}
};
return {x:lx,y:ly}
} BUG 修正后日历HTC
补充:
Box model