Как вставить набор строк таблицы после строки в чистом JS - PullRequest
1 голос
/ 15 апреля 2009

У меня следующая проблема: Мне нужно вставить N строк после строки X. Набор строк, которые мне нужно вставить, передается моей функции как кусок HTML, состоящий из элементов TR. У меня также есть доступ к TR, после которого мне нужно вставить.

Это немного отличается от того, что я делал раньше, когда я заменял TBODY другим TBODY.

У меня проблема в том, что appendChild требует одного элемента, но мне нужно вставить набор.

Редактировать:

Вот решение :

function appendRows(node, html){ 
    var temp = document.createElement("div");
    var tbody = node.parentNode;
    var nextSib = node.nextSibling;

    temp.innerHTML = "<table><tbody>"+html;
    var rows = temp.firstChild.firstChild.childNodes;

    while(rows.length){
        tbody.insertBefore(rows[i], nextSib);
    }
} 

увидеть это в действии:

http://programmingdrunk.com/test.htm

Ответы [ 7 ]

1 голос
/ 16 апреля 2009
if(node.nextSibling && node.nextSibling.nodeName.toLowerCase() === "tr")

Для чего это нужно? Я не думаю, что вам это нужно. Если node.nextSibling имеет значение null, это не имеет значения. Вы можете передать это в insertBefore, и он будет действовать так же, как appendChild.

И в теле нет другого элемента, кроме 'tr'.

for(var i = 0; i < rows.length; i++){
    tbody.insertBefore(rows[i], node.nextSibling);

Это не будет работать для нескольких строк. После того как вы сделали один insertBefore, node.nextSibling теперь будет указывать на строку, которую вы только что вставили; в итоге вы вставите все строки в обратном порядке. Вам нужно будет запомнить оригинал nextSibling.

ETA: плюс, если «row» - это живой NodeList DOM, каждый раз, когда вы вставляете одну из строк в новое тело, она удаляет ее из старого тела! Таким образом, вы уничтожаете список по мере его перебора. Это частая причина ошибок «всех остальных»: вы обрабатываете элемент 0 списка и при этом удаляете его из списка, перемещая элемент 1 туда, где находился элемент 0. Затем вы получаете доступ к новому элементу 1, который является исходным элементом 2, и оригинальный элемент 1 никогда не виден.

Либо сделайте копию списка в обычном неживом «массиве», либо, если вы знаете, что это будет живой список, вы можете использовать более простую форму цикла:

var parent= node.parentNode;
var next= node.nextSibling;
while (rows.length!=0)
    parent.insertBefore(rows[0], next);

Мне нужно вставить набор.

Обычно, когда вы думаете о вставке набора элементов одновременно, вы хотите использовать DocumentFragment. Однако, к сожалению, вы не можете установить «innerHTML» для DocumentFragment, поэтому вам нужно будет установить строки в таблице, как указано выше, а затем переместить их одну за другой в DocumentFragment, а затем вставить «перед DocumentFragment». Хотя теоретически это может быть быстрее, чем добавление в окончательную целевую таблицу (из-за меньшего количества сбоев в списках дочерних узлов), на практике, по моим тестам, это на самом деле не значительно надежнее.

Другим подходом является insertAdjacentHTML, метод расширения только для IE. К сожалению, нельзя вызвать insertAdjacentHTML для дочернего элемента tbody, так же как вы не можете установить tbody.innerHTML из-за ошибки IE. Вы можете установить его внутри DocumentFragment:

var frag= document.createDocumentFragment();
var div= document.createElement(div);
frag.appendChild(div);
div.insertAdjacentHTML('afterEnd', html);
frag.removeChild(div);
node.parentNode.insertBefore(frag, node.nextSibling);

К сожалению, каким-то таинственным образом почему-то очень медленно работает insertAdjacentHTML в этом контексте. Вышеуказанный метод для меня составляет примерно половину скорости вставки один за другим. : - (

1 голос
/ 26 июня 2015

Это работало намного лучше для меня, когда вставлял строку где-либо, кроме последней позиции,

var rowNode = refTable.insertRow(0); var cellNode = rowNode.insertCell();

1 голос
/ 15 апреля 2009

С вашим табличным объектом вы можете вставить в него новую строку.

var tbl = document.getElementById(tableBodyId); 
var lastRow = tbl.rows.length; 
// if there's no header row in the table, then iteration = lastRow + 1 
var iteration = lastRow; 
var row = tbl.insertRow(lastRow);

вставит строку в конец вашей таблицы.

1 голос
/ 15 апреля 2009

Произошла ошибка в IE, использующем innerHTML для вставки строк, поэтому он не будет работать. Прямо изо рта лошади: http://www.ericvasilik.com/2006/07/code-karma.html

Я бы порекомендовал просто обновить tbody, но добавить ваш код в новой структуре.

1 голос
/ 15 апреля 2009

Что сказал altCognito, просто обратите внимание на большую внутреннюю ошибку hHTML на случай, если вы захотите заменить все сразу, используя innerHTML, потому что вы делаете много этого, а операции DOM оказываются слишком медленно.

0 голосов
/ 15 апреля 2009

вам нужно определить, является ли строка X последней строкой ...

//determine if lastRow...
//if not, determine row_after_row_x
for(i in n_rows){
  if(lastRow){
    tbodyObj.appendChild(row_i_of_n);
  } else {
    tbodyObj.insertBefore(row_i_of_n, row_after_row_x);
  }
}
0 голосов
/ 15 апреля 2009

Вам нужно будет добавить их один за другим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...