今天在修正一些需求,在使用以往封裝好日期htc,發(fā)現(xiàn)了一個(gè)bug,如下,在正常情況下點(diǎn)擊輸入框可將隱藏的htc控件能顯示在input正下方。
但在滾動(dòng)層的時(shí)候再點(diǎn)擊輸入框就出現(xiàn)了問題了。
由于blogjava不支持htc上傳。所以沒演示 : (
有BUG的日歷HTC
測試可發(fā)現(xiàn)日歷控件偏位了。滾動(dòng)條向下劃,它也不斷向下偏離input。
查看htc源碼。發(fā)現(xiàn)其是用getDim(el)函數(shù)取得input的X,Y 坐標(biāo)然后將日歷控制定位的。
有bug的取得控件位置的javascript代碼
function getDim(el){
for (var lx=0,ly=0;el!=null;
lx+=el.offsetLeft,ly+=el.offsetTop,el=el.offsetParent); // 用offsetLeft , offsetTop 循環(huán)累加
return {x:lx,y:ly} //返回 input模式x,y 坐標(biāo)
} 現(xiàn)在將input 框架放到div 容器中,然而也設(shè)置了CSS(position:relative;overflow:auto; )
overflow:auto是指當(dāng) 內(nèi)容超出塊的情況下,自動(dòng)顯示滾動(dòng)條
如圖分析:

圖1是正常沒有滾動(dòng)的情況,
圖2、3是滾動(dòng)后的效果(這兩種情況就會(huì)出現(xiàn)問題)
原有bug代碼
for (var lx=0,ly=0;el!=null;
lx+=el.offsetLeft,ly+=el.offsetTop,el=el.offsetParent); 用offsetParent 中的offsetLeft ,offsetTop 不斷累加, 在通常情況下是沒有問題的。
但放到容器中,并且有滾動(dòng)條的情況就會(huì)出現(xiàn)問題了。
先來回顧一下dhtml中對象中的幾個(gè)屬性(更多請看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 (取得了當(dāng)前object相對于其父object的距離),
當(dāng)div滾動(dòng)時(shí)。
這樣計(jì)算其真實(shí)高度就會(huì)有問題(大于其實(shí)際的高度)
代碼改進(jìn),當(dāng)發(fā)現(xiàn)父的tag name 為DIV容器,并設(shè)置了相關(guān)的style CSS(position:relative;overflow:auto; )
那么我們就不再累加這個(gè)
offsetTop,取而代之的公式應(yīng)該是再減去滾動(dòng)上去的隱藏了的高度,也就是的值,如上圖可清晰發(fā)現(xiàn):
ly = ly + (el.offsetTop - el.scrollTop);修正后取得控件位置的javascript代碼,另外左右滾動(dòng)的相應(yīng)原理,在這里沒寫出來
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
補(bǔ)充:
Box model