2009-03-04 47 views
9

我寫了一些Javascript以允許編輯HTML表單中的項目列表,包括添加和刪除項目。知道它在Firefox中工作。在Internet Explorer中嘗試它時,我發現任何添加的項目都沒有與表單一起提交。IE沒有提交;動態添加表單元素;這是一個IE錯誤?

長篇小說簡短...大量簡化,調試,找出哪些行觸發IE忽略新的表單輸入。所以行爲問題解決了。

但現在我必須問:爲什麼?這是一個IE錯誤?

下面是簡化的代碼:

<html> 
<head> 
    <title>Test</title> 
    <script type="text/javascript"> 
     function add() { 
      div = document.getElementById("mylist"); 

      // *** Adding text here works perfectly fine. *** 
      div.innerHTML += " "; 

      e = document.createElement("input"); 
      e.setAttribute("type", "text"); 
      e.setAttribute("name", "field3"); 
      e.setAttribute("value", "--NEWVALUE--"); 
      div.appendChild(e); 

      // *** Adding text here works perfectly fine in Firefox, but for 
      //  Internet Explorer it causes field3 to not be submitted. *** 
      //div.innerHTML += " "; 
     } 
    </script> 
</head> 
<body> 
    <form action="" method="get"> 
     <div id="mylist"> 
      <input type="text" name="field1" value="value1" /> 
      <input type="text" name="field2" value="value2" /> 
     </div> 
     <a href="javascript:" onclick="add()" />Add</a> 
     <input type="submit" value="Submit" /> 
    </form> 
</body> 
</html> 

要嘗試一下,做明顯的:負載在IE中,點擊添加,點擊提交,看看有什麼在地址欄中。如果您取消註釋add()中的最後一行,IE將突然停止報告field3。它可以在Firefox中正常工作。

任何想法?一個好奇的頭腦想知道。 (以及如何在需要時添加文本,以便攜式方式,因此IE很高興?)

回答

7

這是一個IE錯誤嗎?

似乎是這樣。當您通過DOM方法創建一個< input>元素時,IE不會完全拾取'name'屬性。這是因爲元素確實提交了,但如果你試圖獲得元素的'innerHTML'表示,它就會神祕地消失。如果您通過直接寫入到innerHTML來創建元素,則不會發生這種情況。

此外,如果您使用DOM級別0表單導航方法(如'myform.elements.x.value'),則通過'元素'數組訪問可能不起作用(類似地,直接的'myform.x'訪問某些人被錯誤地使用)。無論如何,這些日子你可能更喜歡getElementById()。

所以要麼使用innerHTML 使用DOM方法;最好不要在創建表單域時混合它們。

這是documented (see ‘Remarks’)並最終在IE8中修復。

在任何情況下,永遠不會做:

div.innerHTML + = '...';

這僅是爲了語法糖:

div.innerHTML = div.innerHTML + '...';

換句話說,它有連載的元素的整個子HTML內容,然後做字符串連接,然後重新解析新的字符串回元素,扔掉所有的原始內容。這意味着你失去了無法序列化的東西:IE的僞造的半創建的'name'屬性也意味着你已經附加到每個子元素的任何JavaScript事件處理程序,DOM偵聽器或其他自定義屬性。另外,不必要的序列化/解析循環很慢。

3

IE在運行時更改某些內置屬性非常挑剔。例如,輸入元素的名稱在設置時不能更改。

兩件事情,如果我是你,我會嘗試:

  1. 而不是使用setAttribute(),儘量明確地設置nametypevalue屬性:

    e.name = "text";

  2. 如果沒有按不起作用,您可能必須將所有這些屬性包含在document.createElement()調用中:

    var e = document.createElement("<input type='text' name='field'>");

    這實際上可能會在某些瀏覽器中引發異常。所以最好的跨瀏覽器的方式是:

var e; 
    try { 
    e = document.createElement("<input type='text' name='field'>"); 
    } catch (ex) { 
    e = document.createElement("input"); 
    e.type = 'text'; 
    e.name = 'field'; 
    } 
    e.value = 'value'; 
+0

1上避免的setAttribute。 -1的createElement-with-markup調用,這是一個非常醜陋的IE瀏覽器只有黑客。 – bobince 2009-03-04 19:22:18

+0

我同意這是一個黑客 - 這就是爲什麼我建議海報先嚐試設置屬性。如果這不起作用,我看不到另一種方式來實現他想要發生的事情。 – levik 2009-03-04 19:36:03

3

謝謝bobince和levik爲你解答。使用這些和一些更多的實驗,這裏是我的結論:

  1. 是的,這是一個IE錯誤。

  2. IE 8修復了根據Microsoft的錯誤:「Internet Explorer 8及更高版本可以在運行時使用createElement方法動態創建的元素上設置NAME屬性。」

  3. 問題是這樣的:調用e.setAttribute("name", "field3")只有設置名稱。如果元素沒有發生任何其他事情,它將工作,但如果請求序列化,則名稱不會被序列化。所以當我說innerHTML += " "強制序列化,失去了名稱,所以它並沒有在反序列化時被恢復。沒有名字,沒有包含在表單提交中。

  4. 解決方法#1:e = document.createElement("<input name='field3' />")即使在面對序列化時也能正常工作。

  5. 解決方法#2:與其使用innerHTML + =添加文本,我可以附加如下文本元素:div.appendChild(document.createTextNode(" "));。我認爲必須有更好的方法來添加文本,現在我知道了:-)。

乾杯,
--jsf