今天在修正一些需求,在使用以往封裝好日期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