Не могу установить innerHTML на теле в IE - PullRequest
24 голосов
/ 19 января 2011

У меня есть такая таблица:

<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>

, и метод возвращает мне следующее после запроса ajax:

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

Я хочу изменить innerHTML как

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

Однако, похоже, что IE не может установить innerHTML на <tbody>.Может кто-нибудь помочь мне с простым решением этой проблемы?

Ответы [ 5 ]

32 голосов
/ 19 января 2011

Это правда, innerHTML для элементов tbody только для чтения в IE

свойство доступно для чтения / записи для всех объекты, за исключением следующих, для который доступен только для чтения: COL, COLGROUP, FRAMESET, HEAD, HTML, STYLE, TABLE, TBODY, TFOOT, THEAD, TITLE, TR.

источник: http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx

Вы можете сделать что-то подобное, чтобы обойти это:

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

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

По сути, он создает временный узел, в который вы вводите полный table. Затем он заменяет tbody на tbody из введенного table. Если он окажется медленным, вы можете ускорить его, кэшируя temp вместо того, чтобы создавать его каждый раз.

6 голосов
/ 19 января 2011

Создайте временный узел для хранения таблицы, затем скопируйте их в тело

  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 голос
/ 21 января 2014

Это может быть исправлено созданием shim / polyfill для .innerHTML.Это может заставить вас (вас, дорогой читатель) начать:

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/

1 голос
/ 10 января 2012

Оба ответа выше кажутся немного неясными. Кроме того, созданный div никогда не удаляется, поэтому вызов этих функций постоянно пожирает память. Попробуйте это:


// 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;    

Однако даже с этим кодом MSIE неправильно изменяет размер ячеек таблицы в моем приложении, но я заполняю пустой тег tbody сгенерированным переменным содержимым, в то время как значения colspan ячеек thead установлены на фиксированное значение: максимальное количество ячеек, которые могут быть в сгенерированном теле. В то время как ширина таблицы составляет 50 ячеек, отображаются только два столбца. Возможно, если таблица была изначально заполнена, а ячейки были заменены на ту же внутреннюю структуру, этот метод сработал бы. Google Chrome отлично справляется с перестройкой таблицы, в то время как браузер Opera для настольных компьютеров может просто изменить размер на большее количество столбцов, но если вы удалите столбцы, оставшаяся ширина столбцов останется такой же узкой, как и раньше; однако в Opera, скрывая таблицу (display = none), затем повторно ее отображая (display = table), сгенерированные ячейки tbody таблицы затем масштабируются должным образом. Я отказался от Firefox. Это MSIE-6 2012 года - кошмар для разработки, для которого необходимо добавить дополнительную разметку, просто чтобы заставить работать HTML-CSS макеты, потому что она не соответствует стандартам, которые сейчас делает даже MSIE. Поэтому я не проверял работу tbody.innerHTML в Firefox.

0 голосов
/ 11 октября 2017
<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...