2011-03-22 74 views
1

我正在開發一個需要能夠放入其他應用程序的asp.net控件。該控件基本上是一個自定義下拉列表,其中一個div在單擊另一個元素時顯示或隱藏。絕對定位中斷在IE8中

我遇到的問題是試圖讓動態div對齊被點擊的元素下方。我寫了一個javascript函數,它理論上應該允許我指定兩個元素和所需的對齊,然後將第二個元素移動到與第一個元素相關的正確位置。

我有三個測試用例,它們與我目前所期望的這個控件將被使用的地方有關,我的所有三種情況下我的當前標記和JavaScript工作對於IE7,但對於FF3.5和IE8標準中的一種情況失敗模式。我一直在玩這個遊戲一段時間,還沒有拿出一個解決問題的答案,而沒有打破其他問題。 (請注意,我的用戶有90%以上在IE7上,並且向IE8緩慢遷移)

我正在尋找除了向頁面添加兼容模式指令之外的任何建議,它確實解決了IE8中的問題,但我更願意如果可能的話可以選擇,因爲我可能無法控制使用的位置。這裏是一個HTML文檔,它說明了相關的標記和JavaScript以及測試用例。第三種情況是存在問題的,而不是在輸入元素下整齊排列,div垂直重疊,並向右偏移與選擇元素寬度相等的距離。

(注意,真正的頁面使用改編自一個由埃裏克·邁耶出版,包括/忽略這個樣式表重置樣式表對這些測試用例沒有相關的影響。)

<!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></title> 
</head> 
<body> 
<script type="text/javascript"> 
    var VAlign = { "top": -1, "center": 0, "bottom": 1 }; 
    var HAlign = { "left": -1, "center": 0, "right": 1 }; 
    function AlignElements(element1, vAlign1, hAlign1, element2, vAlign2, hAlign2) { 
     var List1 = BuildOffsetList(element1); 
     var List2 = BuildOffsetList(element2); 
     var Index1 = List1.length - 1; 
     var Index2 = List2.length - 1; 

     while (Index1 >= 0 && Index2 >= 0 && List1[Index1] == List2[Index2]) { 
      Index1--; 
      Index2--; 
     } 

     element2.style.top = ""; 
     element2.style.left = ""; 

     var OT1 = 0; 
     var OL1 = 0; 
     var OT2 = 0; 
     var OL2 = 0; 

     while (Index1 >= 0) { 
      OT1 += List1[Index1].offsetTop; 
      OL1 += List1[Index1].offsetLeft; 
      Index1--; 
     } 

     while (Index2 >= 0) { 
      OT2 += List2[Index2].offsetTop; 
      OL2 += List2[Index2].offsetLeft; 
      Index2--; 
     } 

     var top = (OT1 - OT2); 
     if (vAlign1 == VAlign.bottom) { 
      top += element1.offsetHeight; 
     } else if (vAlign1 == VAlign.center) { 
      top += (element1.offsetHeight/2); 
     } 
     if (vAlign2 == VAlign.bottom) { 
      top -= element2.offsetHeight; 
     } else if (vAlign2 == VAlign.center) { 
      top -= (element2.offsetHeight/2); 
     } 

     var left = (OL1 - OL2); 
     if (hAlign1 == HAlign.right) { 
      left += element1.offsetWidth; 
     } else if (hAlign1 == HAlign.center) { 
      left += (element1.offsetWidth/2); 
     } 
     if (hAlign2 == HAlign.right) { 
      left -= element2.offsetWidth; 
     } else if (hAlign2 == HAlign.center) { 
      left -= (element2.offsetWidth/2); 
     } 

     element2.style.top = top + "px"; 
     element2.style.left = left + "px"; 
    } 

    function BuildOffsetList(elelment) { 
     var I = 0; 
     var List = new Array(); 
     var Element = elelment; 
     while (Element) { 
      List[I] = Element; 
      Element = Element.offsetParent; 
      I++; 
     } 
     return List; 
    } 
</script> 
Case 1 
<div> 
    <div id="control1" style=" display:inline; position:relative;"> 
     <div id="control1_div1" style="background-color:Blue; height:75px; width:150px; position:absolute;"></div> 
     <input id="control1_txt1" type="text" style="width:150px;" /> 
     <script type="text/javascript"> 
      AlignElements(document.getElementById("control1_txt1"), VAlign.bottom, HAlign.left, document.getElementById("control1_div1"), VAlign.top, HAlign.left); 
     </script> 
    </div> 
</div> 
<div style="height:100px;"></div> 
Case 2 
<div> 
    <div id="Nav" style="float:left; width:200px; height:150px; background-color:Aqua;"></div> 
    <div id="Content" style="margin-left:200px; height:150px; background-color:#ddd;"> 
     <div style="margin-left:100px;"> 
      <h5 style="float:left; margin-left:-100px; width:90px; margin-right:10px; text-align:right; font-weight:.9em;">Label</h5> 
      <div id="control2" style=" display:inline; position:relative;"> 
       <div id="control2_div1" style="background-color:Blue; height:75px; width:150px; position:absolute;"></div> 
       <input id="control2_txt1" type="text" style="width:150px;" /> 
       <script type="text/javascript"> 
        AlignElements(document.getElementById("control2_txt1"), VAlign.bottom, HAlign.left, document.getElementById("control2_div1"), VAlign.top, HAlign.left); 
       </script> 
      </div> 
     </div> 
    </div> 
</div> 
<div style="height:100px;"></div> 
Case 3 
<div> 
    <select><option>something</option></select> 
    <br /> 
    <select><option>something else</option></select> 
    <div id="control3" style=" display:inline; position:relative;"> 
     <div id="control3_div1" style="background-color:Blue; height:75px; width:150px; position:absolute;"></div> 
     <input id="control3_txt1" type="text" style="width:150px;" /> 
     <script type="text/javascript"> 
      AlignElements(document.getElementById("control3_txt1"), VAlign.bottom, HAlign.left, document.getElementById("control3_div1"), VAlign.top, HAlign.left); 
     </script> 
    </div> 
</div> 
</body> 
</html> 
+0

使用jQuery它應該是更容易放置元素之外/低於其他元素..這是給你的一個有效的選擇嗎? – 2011-03-22 18:04:18

+0

我無法控制所有這將被使用,所以我努力留在標準的JavaScript領域。如果一切都失敗了,我可能會逃避導入另一個庫來構建,但我寧願避免它。 – Rozwel 2011-03-22 18:18:37

回答

0

感謝陰影嚮導讓我在正確的方向思考。原來問題是,當我清除頂部和左側屬性時,絕對定位的元素不會移動到0,0點。如果在計算偏移量差異之前將代碼更改爲明確地將它們設置爲0,0,那麼所有內容都可以很好地工作。

element2.style.top = ""; 
    element2.style.left = ""; 

成爲

element2.style.top = "0px"; 
    element2.style.left = "0px"; 
1

第三種情況由於父母divinline顯示正在分解 - 據我所知,它導致相對位置無效。

爲了測試這種情況下使用浮動,而不是,這裏是工作示例: http://jsfiddle.net/yahavbr/estYF/1/

+0

漂浮會導致需要使用這些頁面上的問題,但要讓我的大腦進入正確的軌道。 – Rozwel 2011-03-23 12:50:42

+0

Cheers @Rozwel,感謝您分享「真正的」解決方案! :) – 2011-03-23 13:00:44