2011-01-18 69 views
22

Tôi có một bảng như thế này:Không thể thiết lập innerHTML trên tbody trong IE

<table> 
<thead> 
    <tr> 
     <th colspan="1">a</th> 
     <th colspan="3">b</th> 
    </tr> 
</thead> 
<tbody id="replaceMe"> 
    <tr> 
     <td>data 1</td> 
     <td>data 2</td> 
     <td>data 3</td> 
     <td>data 4</td> 
    </tr> 
</tbody> 
</table> 

và một phương thức trả về cho tôi sau khi một yêu cầu ajax:

<tr> 
    <td>data 1 new</td> 
    <td>data 2 new</td> 
    <td>data 3 new</td> 
    <td>data 4 new</td> 
</tr> 

Tôi muốn thay đổi innerHTML like

document.getElementById('replaceMe').innerHTML = data.responseText; 

Tuy nhiên, có vẻ như IE không thể đặt innerHTML trên <tbody>. Bất cứ ai có thể giúp tôi với một workaround đơn giản cho vấn đề này?

+2

cũng vậy, sử dụng thư viện như jQuery KHÔNG PHẢI là một tùy chọn. – tester

Trả lời

32

Đó là sự thật, innerHTML trên các yếu tố tbody là readonly trong IE

Khu nghỉ dưỡng được đọc/ghi cho tất cả đối tượng ngoại trừ những điều sau đây, cho mà nó được read-only: COL, COLGROUP, FRAMESET, HEAD, HTML, PHONG CÁCH, BẢNG, TBODY, TFOOT, THEAD, TITLE, TR.

nguồn: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx

Bạn có thể làm một cái gì đó như thế này để làm việc xung quanh nó:

function setTBodyInnerHTML(tbody, html) { 
    var temp = tbody.ownerDocument.createElement('div'); 
    temp.innerHTML = '<table>' + html + '</table>'; 

    tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody); 
} 

Về cơ bản nó tạo ra một nút tạm thời vào mà bạn tiêm đầy đủ table. Sau đó, nó thay thế các tbody với tbody từ tiêm table. Nếu nó được chứng minh là chậm, bạn có thể làm cho nó nhanh hơn bằng cách lưu vào bộ nhớ đệm temp thay vì tạo nó mỗi lần.

+0

Tôi có thể sử dụng điều này như thế nào? –

+1

var myTableBody = document.getElementById ('giá trị của id tbody của bạn'); setTBodyInnerHTML (myTableBody, "giá trị để thêm"); – Matoeil

+2

Không tốt như vậy: Thay thế mất tất cả các thuộc tính ban đầu, như id = "replaceMe" trong câu hỏi. –

6

Tạo một nút tạm để lưu trữ một bảng trong, sau đó sao chép chúng vào tbody

var tempNode = document.createElement('div'); 
    tempNode.innerHTML = "<table>" + responseText+ "</table>"; 

    var tempTable = tempNode.firstChild; 
    var tbody = // get a reference to the tbody 
    for (var i=0, tr; tr = tempTable.rows[i]; i++) { 
    tbody.appendChild(tr); 
    } 
1

Cả hai câu trả lời ở trên dường như một chút không rõ ràng. Thêm vào đó, div được tạo sẽ không bao giờ bị loại bỏ, vì vậy hãy gọi những hàm đó liên tục ăn bộ nhớ. Hãy thử điều này:


// this function must come before calling it to properly set “temp” 
function MSIEsetTBodyInnerHTML(tbody, html) { //fix MS Internet Exploder’s lameness 
    var temp = MSIEsetTBodyInnerHTML.temp; 
    temp.innerHTML = '<table><tbody>' + html + '</tbody></table>'; 
    tbody.parentNode.replaceChild(temp.firstChild.firstChild, tbody); } 
MSIEsetTBodyInnerHTML.temp = document.createElement('div'); 

if (navigator && navigator.userAgent.match(/MSIE/i)) 
    MSIEsetTBodyInnerHTML(tbody, html); 
else //by specs, you can not use “innerHTML” until after the page is fully loaded 
    tbody.innerHTML=html;  

Ngay cả với mã này, tuy nhiên, MSIE dường như không thay đổi kích thước đúng các tế bào bảng trong ứng dụng của tôi, nhưng tôi điền thẻ tbody trống với nội dung thay đổi được tạo ra, trong khi thead giá trị colspan của ô được đặt thành giá trị cố định: số lượng ô tối đa có thể có trong tbody được tạo. Trong khi bảng tbody là 50 ô rộng, chỉ có hai cột hiển thị. Có lẽ nếu bảng đã được lấp đầy ban đầu, và các tế bào được thay thế bằng cùng một cấu trúc bên trong, phương pháp này sẽ hoạt động. Chrome của Google làm một công việc tuyệt vời để xây dựng lại bảng, trong khi trình duyệt trên máy tính để bàn của Opera có thể thay đổi kích thước thành nhiều cột hơn, nhưng nếu bạn xóa cột, chiều rộng cột còn lại vẫn hẹp như trước; tuy nhiên với Opera, bằng cách ẩn bảng (display = none) sau đó hiển thị lại nó (display = table), các tế bào bảng được tạo ra sau đó kích thước đúng. Tôi đã từ bỏ Firefox. Đó là MSIE-6 năm 2012 - một cơn ác mộng để phát triển mà phải có thêm đánh dấu bổ sung chỉ để làm cho HTML-CSS bố trí làm việc vì nó không phù hợp với tiêu chuẩn mà ngay cả MSIE hiện nay. Vì vậy, tôi đã không thử nghiệm các hoạt động tbody.innerHTML trong Firefox.

+2

Nút này được thu thập rác sau khi thoát khỏi hàm vì nó không được gắn với DOM. –

1

Điều này có thể được khắc phục bằng cách tạo một shim/polyfill cho .innerHTML.Điều này có thể giúp bạn (bạn thân mến reader) bắt đầu:

if (/(msie|trident)/i.test(navigator.userAgent)) { 
var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get 
var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set 
Object.defineProperty(HTMLElement.prototype, "innerHTML", { 
    get: function() {return innerhtml_get.call (this)}, 
    set: function(new_html) { 
    var childNodes = this.childNodes 
    for (var curlen = childNodes.length, i = curlen; i > 0; i--) { 
    this.removeChild (childNodes[0]) 
    } 
    innerhtml_set.call (this, new_html) 
    } 
}) 
} 

var mydiv = document.createElement ('div') 
mydiv.innerHTML = "test" 
document.body.appendChild (mydiv) 

document.body.innerHTML = "" 
console.log (mydiv.innerHTML) 

http://jsfiddle.net/DLLbc/9/

0

tôi tìm thấy bản thân mình trong tình cảnh tương tự ngày hôm nay.

Tôi đã giải quyết được sự cố của mình bằng cách thay thế toàn bộ đánh dấu bảng bằng các divs nổi và css mô phỏng hành vi của bảng. Bằng cách này tôi đã có thể sử dụng innerHTML trong IE mà không có vấn đề gì.

Mặc dù đây không phải là giải pháp cho bất kỳ ai, nếu bạn được phép vào bảng của mình với các div nổi, tôi khuyên bạn nên làm như vậy.

0
<table id="table"> 
<thead> 
    <tr> 
     <th colspan="1">a</th> 
     <th colspan="3">b</th> 
    </tr> 
</thead> 
<tbody id="replaceMe"> 
    <tr> 
     <td>data 1</td> 
     <td>data 2</td> 
     <td>data 3</td> 
     <td>data 4</td> 
    </tr> 
</tbody> 
</table> 
<button type="button" onclick="replaceTbody()">replaceTbody</button> 
<script> 
function $(id){ 
    return document.getElementById(id); 
} 

function replaceTbody(){ 
    var table = $('table'); 
    table.removeChild($('replaceMe')); 
    var tbody = document.createElement("tbody"); 
    tbody.setAttribute("id","replaceMe"); 
    table.appendChild(tbody); 

    var tr = document.createElement('tr'); 
    for(var i=1;i<5;i++){ 
     var td = document.createElement('td'); 
     td.innerHTML = 'newData' + i; 
     tr.appendChild(td); 
    } 
    tbody.appendChild(tr); 
} 
</script> 
+0

Bạn có thể thêm tóm tắt ngắn gọn về giải pháp được đề xuất không? – mrtig

Các vấn đề liên quan