JS. Как заменить элемент html на другой элемент/текст, представленный в строке?

У меня проблема с заменой элементов html.

Например, вот таблица:

<table>
    <tr>
        <td id="idTABLE">0</td>
        <td>END</td>
    </tr>
</table>

(это может быть div, span, anything)

И строка в JavaScript:

var str = '<td>1</td><td>2</td>';

(Это может быть что угодно, 123 text, <span>123 element</span> 456 или <tr><td>123</td> или что-то еще)

Как заменить элемент idTABLE на str?

Итак:

<table>
    <tr>
        <td id="idTABLE">0</td>
        <td>END</td>
    </tr>
</table>

становится:

<table>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>END</td>
    </tr>
</table> 
<!-- str = '<td>1</td><td>2</td>'; -->

<table>
    <tr>
        123 text
        <td>END</td>
    </tr>
</table>
<!-- str = '123 text' -->

<table>
    <tr> 
        <td>123</td> 
        <td>END</td>
    </tr>
</table>
<!-- str = '<td>123</td>' -->

Я пробовал createElement, replaceChild, cloneNode, но без результата вообще = (

Ответ 1

Поскольку код JQuery replaceWith() был слишком громоздким, сложным и сложным, вот мое собственное решение. =)

Лучший способ - использовать свойство outerHTML, но он еще не перекрестно настроен, поэтому я сделал какой-то трюк, довольно странный, но простой.

Вот код

var str = '<a href="http://www.com">item to replace</a>'; //it can be anything
var Obj = document.getElementById('TargetObject'); //any element to be fully replaced
if(Obj.outerHTML) { //if outerHTML is supported
    Obj.outerHTML=str; ///it simple replacement of whole element with contents of str var
}
else { //if outerHTML is not supported, there is a weird but crossbrowsered trick
    var tmpObj=document.createElement("div");
    tmpObj.innerHTML='<!--THIS DATA SHOULD BE REPLACED-->';
    ObjParent=Obj.parentNode; //Okey, element should be parented
    ObjParent.replaceChild(tmpObj,Obj); //here we placing our temporary data instead of our target, so we can find it then and replace it into whatever we want to replace to
    ObjParent.innerHTML=ObjParent.innerHTML.replace('<div><!--THIS DATA SHOULD BE REPLACED--></div>',str);
}

Что все

Ответ 2

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

function replaceTargetWith( targetID, html ){
  /// find our target
  var i, tmp, elm, last, target = document.getElementById(targetID);
  /// create a temporary div or tr (to support tds)
  tmp = document.createElement(html.indexOf('<td')!=-1?'tr':'div'));
  /// fill that div with our html, this generates our children
  tmp.innerHTML = html;
  /// step through the temporary div children and insertBefore our target
  i = tmp.childNodes.length;
  /// the insertBefore method was more complicated than I first thought so I 
  /// have improved it. Have to be careful when dealing with child lists as  
  /// they are counted as live lists and so will update as and when you make
  /// changes. This is why it is best to work backwards when moving children 
  /// around, and why I'm assigning the elements I'm working with to `elm` 
  /// and `last`
  last = target;
  while(i--){
    target.parentNode.insertBefore((elm = tmp.childNodes[i]), last);
    last = elm;
  }
  /// remove the target.
  target.parentNode.removeChild(target);
}

пример использования:

replaceTargetWith( 'idTABLE', 'I <b>can</b> be <div>anything</div>' );

демо:

Используя .innerHTML нашего временного div, мы создадим TextNodes и Elements, которые нам нужно вставить без какой-либо тяжелой работы. Но вместо того, чтобы вставлять временный div, это может дать нам разметку, которую мы не хотим - мы можем просто сканировать и вставлять ее.

... либо это, либо посмотрите на использование jQuery и метода replaceWith.

jQuery('#idTABLE').replaceWith('<blink>Why this tag??</blink>');


обновление 2012/11/15

В ответ на комментарий EL 2002 выше:

Это не всегда возможно. Например, когда createElement('div') и установите его innerHTML как <td>123</td>, этот div станет <div>123</div> (js выбрасывает неправильный тег td)

Вышеупомянутая проблема, очевидно, также отрицает мое решение - я обновил свой код выше (по крайней мере, для проблемы td). Однако для определенного HTML это произойдет независимо от того, что вы делаете. Все пользовательские агенты интерпретируют HTML через свои собственные правила синтаксического анализа, но почти все они будут пытаться автоматически исправить плохой HTML. Единственный способ добиться того, о чем вы говорите (в некоторых ваших примерах) - полностью вывести HTML из DOM и манипулировать им как строку. Это будет единственный способ получить строку разметки со следующим (jQuery тоже не обойдет эту проблему):

<table><tr>123 text<td>END</td></tr></table>

Если вы затем возьмете эту строку, введите ее в DOM, в зависимости от браузера вы получите следующее:

123 text<table><tr><td>END</td></tr></table>

<table><tr><td>END</td></tr></table>

Единственный вопрос, который остается, - это то, почему вы хотели бы получить разбитый HTML в первую очередь?:)

Ответ 3

Используя jQuery, вы можете сделать это:

var str = '<td>1</td><td>2</td>';
$('#__TABLE__').replaceWith(str);

http://jsfiddle.net/hZBeW/4/

Или в чистом javascript:

var str = '<td>1</td><td>2</td>';
var tdElement = document.getElementById('__TABLE__');
var trElement = tdElement.parentNode;
trElement.removeChild(tdElement);
trElement.innerHTML = str + trElement.innerHTML;

http://jsfiddle.net/hZBeW/1/

Ответ 5

Если вам нужно фактически заменить td, который вы выбираете из DOM, вам нужно сначала перейти к parentNode, затем заменить содержимое заменить innerHTML на новую строку html, представляющую что ты хочешь. Трюк преобразует ячейку first-table в строку, поэтому вы можете использовать ее в методе замены строк.

Я добавил пример скрипки: http://jsfiddle.net/vzUF4/

<table><tr><td id="first-table-cell">0</td><td>END</td></tr></table>

<script>
  var firstTableCell = document.getElementById('first-table-cell');
  var tableRow = firstTableCell.parentNode;
  // Create a separate node used to convert node into string.
  var renderingNode = document.createElement('tr');
  renderingNode.appendChild(firstTableCell.cloneNode(true));
  // Do a simple string replace on the html
  var stringVersionOfFirstTableCell = renderingNode.innerHTML;
  tableRow.innerHTML = tableRow.innerHTML.replace(stringVersionOfFirstTableCell,
    '<td>0</td><td>1</td>');
</script>

Большая сложность заключается в том, что вы смешиваете методы DOM со строковыми методами. Если методы DOM работают для вашего приложения, было бы очень полезно использовать их. <Удаp > Вы также можете сделать это с помощью чистых методов DOM (document.createElement, removeChild, appendChild), но для этого требуется больше строк кода, и ваш вопрос явно сказал, что вы хотите использовать строку.

Ответ 6

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

Если искаженный ввод неизбежен, то без какого-либо сложного анализа (желательно в отдельной функции) вы можете получить плохой HTML (как вы делаете в своем втором примере... что плохо, правильно?).

Я предполагаю, что вы хотите, чтобы функция вставляла столбцы в таблицу из 1 строки. В этом случае ваше содержимое должно быть передано как массив (без тэгов таблицы, tr, td). Каждый элемент массива будет иметь один столбец.

HTML

<table id="__TABLE__"><tr><td></td></tr></table>

JS

с помощью jQuery для краткости...

function insert_columns (columns)
{
    var $row = $('<tr></tr>');

    for (var i = 0; i < columns.length; i++)
        $row.append('<td>'+columns[i]+'</td>');

    $('#__TABLE__').empty(); // remove everything inside

    $('#__TABLE__').append($row);
}

Итак, тогда...

insert_columns(['hello', 'there', 'world']);

Результат

<table id="__TABLE__"><tr><td>hello</td><td>there</td><td>world</td></tr></table>

Ответ 7

используйте атрибут innerHTML "

каким-то образом выберите таблицу:

var a = document.getElementById('table, div, whatever node, id')
a.innerHTML = your_text

Ответ 8

idTABLE.parentElement.innerHTML =  '<span>123 element</span> 456';

В то время как это работает, рекомендуется использовать getElementById: Элементы дерева DOM с идентификаторами становятся глобальными переменными?

replaceChild будет работать нормально, если вы хотите решить проблему создания своей замены, по элементам, используя document.createElement и appendChild, но я не вижу смысла.