Как изменить HTML-таблицу с помощью JavaScript, чтобы увеличить rowspan, не вызывая reflow?

#javascript #dom

#javascript #dom

Вопрос:

Чтобы изменить HTML-таблицу так, чтобы в какой-либо ячейке было указано rowspan=»n» (для увеличения rowspan), вы должны удалить n ячеек ниже той, которая расширяется.

Исходный HTML-код (HTML-структура) выглядит следующим образом

 <table border="1">
<tr id="1"><td>1</td><td>Zubenelgenubi</td></tr>
<tr id="2"><td>2</td><td>Algorab</td></tr>
<tr id="3"><td>3</td><td>Almach</td></tr>
<tr id="4"><td>4</td><td>Alula_Borealis</td></tr>
<tr id="5"><td>5</td><td>Rigil_Kentaurus</td></tr>
<tr id="6"><td>6</td><td>Menkent</td></tr>
</table>
  

и мне нравится преобразовывать это во что-то вроде этого:

 <table border="1">
<tr id="1"><td>1</td><td>Zubenelgenubi</td></tr>
<tr id="2"><td>2</td><td>Algorab</td></tr>
<tr id="3" rowspan="3"><td>3</td><td>Almach</td></tr>
<tr id="4">          <td>Alula_Borealis</td></tr>
<tr id="5">          <td>Rigil_Kentaurus</td></tr>
<tr id="6"><td>6</td><td>Menkent</td></tr>
</table>
  

К сожалению, форматирование SO не поддерживает таблицы ни в Markdown, ни в HTML.

Возможно ли это сделать, не вызывая ненужной перепрошивки? Я имею в виду здесь что-то лучшее, чем просто

 for (var i = 0; i < numlines; i  ) {
   ...
   if (i === 0) {
      td.rowSpan = numlines;
      ...
   } else {
      tr.deleteCell(0); // or td.parentNode.removeChild(td);
   }
}
  

что, я думаю, вызывает перепрошивку после каждой итерации.

При добавлении элементов можно использовать DocumentFragment; что делать при изменении количества элементов одновременно?


Редактировать: добавлено 03-05-2011
Решение с использованием объекта Range (версия W3C DOM)

 var range = document.createRange();
range.setStartBefore(document.getElementById(start ''));
range.setEndBefore(document.getElementById(start numlines ''));

var fragment = range.cloneContents();

for (var i = 0; i < numlines; i  ) {
    var rownum = start   i;
    var row = fragment.getElementById(rownum.toString()); // not always work

    var td = row.firstChild;
    if (i === 0) {
        td.style.backgroundColor = 'yellow';
        td.rowSpan = num.toString();
    } else {
        td.parentNode.removeChild(td);
    }

}
range.deleteContents();

var rowAfter = document.getElementById(start num '');
rowAfter.parentNode.insertBefore(fragment, rowAfter);
  

Обратите внимание, что по какой-то причине fragment.getElementById у меня это не сработало, поэтому мне пришлось схитрить, зная, какие узлы там есть.

deleteContents insertBefore необходим, потому что, к сожалению, table.replaceChild(range, fragment); не работает (где table находится элемент, из которого был извлечен диапазон).

Ответ №1:

  1. Попробуйте заставить элемент таблицы отображать: none до цикла и восстановить отображение после.
  2. Другим вариантом было бы назначить фиксированные размеры и использовать overflow: hidden на время выполнения тела цикла. Это должно изолировать дерево обновлений только по таблице. Теоретически.
  3. И последнее — составить HTML-код таблицы и заменить таблицу целиком — это будет сделано за одну транзакцию.

Комментарии:

1. Объявление 3: Могу ли я использовать диапазон , чтобы не заменять всю таблицу целиком?