JS. How to replace html element with another eleme

2019-03-11 01:11发布

问题:

I have a problem with replacing html elements.

For example, here is a table:

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

(it can be div, span, anything)

And string in JavaScript:

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

(It can be anything, 123 text, <span>123 element</span> 456 or <tr><td>123</td> or anything)

How can I replace element idTABLE with str?

So:

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

Becomes:

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

I tried createElement, replaceChild, cloneNode, but with no result at all =(

回答1:

As the Jquery replaceWith() code was too bulky, tricky and complicated, here's my own solution. =)

The best way is to use outerHTML property, but it is not crossbrowsered yet, so I did some trick, weird enough, but simple.

Here is the code

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's 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);
}

That's all



回答2:

Using jQuery you can do this:

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

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

Or in pure 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/



回答3:

Because you are talking about your replacement being anything, and also replacing in the middle of an element's children, it becomes more tricky than just inserting a singular element, or directly removing and appending:

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's 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);
}

example usage:

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

demo:

  • http://jsfiddle.net/97H5Y/1/

By using the .innerHTML of our temporary div this will generate the TextNodes and Elements we need to insert without any hard work. But rather than insert the temporary div itself -- this would give us mark up that we don't want -- we can just scan and insert it's children.

...either that or look to using jQuery and it's replaceWith method.

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


update 2012/11/15

As a response to EL 2002's comment above:

It not always possible. For example, when createElement('div') and set its innerHTML as <td>123</td>, this div becomes <div>123</div> (js throws away inappropriate td tag)

The above problem obviously negates my solution as well - I have updated my code above accordingly (at least for the td issue). However for certain HTML this will occur no matter what you do. All user agents interpret HTML via their own parsing rules, but nearly all of them will attempt to auto-correct bad HTML. The only way to achieve exactly what you are talking about (in some of your examples) is to take the HTML out of the DOM entirely, and manipulate it as a string. This will be the only way to achieve a markup string with the following (jQuery will not get around this issue either):

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

If you then take this string an inject it into the DOM, depending on the browser you will get the following:

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

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

The only question that remains is why you would want to achieve broken HTML in the first place? :)



回答4:

You would first remove the table, then add the new replacement to the table's parent object.

Look up removeChild and appendChild

http://javascript.about.com/library/bldom09.htm

https://developer.mozilla.org/en-US/docs/DOM/Node.appendChild

Edit: jQuery .append allows sting-html without removing tags: http://api.jquery.com/append/



回答5:

Your input in this case is too ambiguous. Your code will have to know if it should just insert the text as-is or parse out some HTML tags (or otherwise wind up with bad HTML). This is unneeded complexity that you can avoid by adjusting the input you provide.

If the garbled input is unavoidable, then without some sophisticated parsing (preferably in a separate function), you could end up with some bad HTML (like you do in your second example... which is Bad, right?).

I'm guessing you want a function to insert columns into a 1-row table. In this case, your contents should be passed in as an array (without table, tr, td tags). Each array element will be one column.

HTML

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

JS

using jQuery for brevity...

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);
}

So then...

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

Result

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


回答6:

If you need to actually replace the td you are selecting from the DOM, then you need to first go to the parentNode, then replace the contents replace the innerHTML with a new html string representing what you want. The trick is converting the first-table-cell to a string so you can then use it in a string replace method.

I added a fiddle example: 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>

A lot of the complexity here is that you are mixing DOM methods with string methods. If DOM methods work for your application, it would be much bette to use those. You can also do this with pure DOM methods (document.createElement, removeChild, appendChild), but it takes more lines of code and your question explicitly said you wanted to use a string.



回答7:

use the attribute "innerHTML"

somehow select the table:

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


回答8:

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

while this works, it's still recommended to use getElementById: Do DOM tree elements with ids become global variables?

replaceChild would work fine if you want to go to the trouble of building up your replacement, element by element, using document.createElement and appendChild, but I don't see the point.