Adam Halasz
Adam Halasz

Reputation: 58301

Javascript: How to change a nodes name?

For example I have this HTML:

<body>
    <div>Text</div>
</body>

And I would like to change the div to something else like p.

This is what I have tried but doesn't works:

var div = document.getElementsByTagName("div")[0]; // Get Element
    div.nodeName = "p"; // Change It's Node Name to P

Please no libraries, and I don't really want to replace the actual div with a new p :)

Upvotes: 4

Views: 4940

Answers (5)

Felix Kling
Felix Kling

Reputation: 816364

You cannot just change an element. You have to create a new one. E.g.:

var div = document.getElementsByTagName("div")[0];
var p = document.createElement('p');
p.innerHTML = div.innerHTML;
div.parentNode.replaceChild(p, div);

But this could lead to invalid markup, if the original element contains nodes that cannot be descendants of the new node.

Reference: document.createElement, Node.replaceChild


Note: A better version (because it doesn't depend on serializing DOM to text and back and preserves attributes), can be found at https://stackoverflow.com/a/8584158/218196 .

Upvotes: 10

M&#225;t&#233; Safranka
M&#225;t&#233; Safranka

Reputation: 4116

The reason you can't just change the tagName property is because different HTML tags are actually different classes of objects. A div tag is an HTMLDivElement instance, a p tag is an HTMLParagraphElement instance, and so on. These classes can have vastly different properties and interfaces, so turning one into another is not as trivial as you'd think.

Upvotes: 2

wybe
wybe

Reputation: 624

I solved this in an XML scenario (eg. where there is no innerHTML) like so:

function renameNode (node, newNodeName) {
    const newNode = node.ownerDocument.createElement(newNodeName);
    Array.from(node.attributes).forEach(attr => newNode.setAttribute(attr.localName, attr.value));
    Array.from(node.childNodes).forEach(childNode => newNode.appendChild(childNode));

    node.parentElement.insertBefore(newNode, node);
    node.parentElement.removeChild(node);
}

Does not return anything, but will update your DOM.

Upvotes: 0

Chris Baker
Chris Baker

Reputation: 50592

You cannot. The propery you're after is tagName, but it is read only. You would instead have to create a new node of the desired type, then transfer the innerHTML (and any other properties like className or style) to the new node. Then, insert the new node into the old node's parent, then remove the old node (or use replaceChild).

In other words, the long road is the only road.

Upvotes: 0

lonesomeday
lonesomeday

Reputation: 237845

You can't.

As the MDC docs say:

nodeName is a read-only attribute.

You'll have to create a new element and give it the right content and attributes.

Upvotes: 1

Related Questions