17

I want to know if we can change tag name in a tag rather than its content. I have this content

<wns id="93" onclick="wish(id)">...</wns>    

In the wish function I want to change it to

<lmn id="93" onclick="wish(id)">...</lmn>

I tried this way:

document.getElementById("99").innerHTML = document.getElementById("99").replace(/wns/g,"lmn");

but it does not work.

Please note that I just want to alter that specific tag with specific id rather than every wns tag.

2
  • 1
    First of all, those tagnames are not valid HTML, and no, you can't change a tagname in HTML (you can however replace it). Commented Feb 26, 2013 at 10:29
  • Perhaps this might help you: stackoverflow.com/questions/918792/… Commented Feb 26, 2013 at 10:31

6 Answers 6

39

You can't change the tag name of an existing DOM element; instead, you have to create a replacement and then insert it where the element was.

The basics of this are to move the child nodes into the replacement and similarly to copy the attributes. So for instance:

var wns = document.getElementById("93");
var lmn = document.createElement("lmn");
var index;

// Copy the children
while (wns.firstChild) {
    lmn.appendChild(wns.firstChild); // *Moves* the child
}

// Copy the attributes
for (index = wns.attributes.length - 1; index >= 0; --index) {
    lmn.attributes.setNamedItem(wns.attributes[index].cloneNode());
}

// Replace it
wns.parentNode.replaceChild(lmn, wns);

Live Example: (I used div and p rather than wns and lmn, and styled them via a stylesheet with borders so you can see the change)

document.getElementById("theSpan").addEventListener("click", function() {
  alert("Span clicked");
}, false);

document.getElementById("theButton").addEventListener("click", function() {

  var wns = document.getElementById("target");
  var lmn = document.createElement("p");
  var index;

  // Copy the children
  while (wns.firstChild) {
    lmn.appendChild(wns.firstChild); // *Moves* the child
  }

  // Copy the attributes
  for (index = wns.attributes.length - 1; index >= 0; --index) {
    lmn.attributes.setNamedItem(wns.attributes[index].cloneNode());
  }

  // Insert it
  wns.parentNode.replaceChild(lmn, wns);
}, false);
div {
  border: 1px solid green;
}
p {
  border: 1px solid blue;
}
<div id="target" foo="bar" onclick="alert('hi there')">
  Content before
  <span id="theSpan">span in the middle</span>
  Content after
</div>
<input type="button" id="theButton" value="Click Me">

See this gist for a reusable function.


Side note: I would avoid using id values that are all digits. Although they're valid in HTML (as of HTML5), they're invalid in CSS and thus you can't style those elements, or use libraries like jQuery that use CSS selectors to interact with them.

Sign up to request clarification or add additional context in comments.

6 Comments

Actually you can! Dirty example: tag.outerHTML = "<" + newName + ">" + tag.innerHTML + "</" + newName + ">";
@Bitterblue: Nope. :-) That creates a new element and swaps it in for the old one. And just like other ways you do that, you lose event handlers, you lose expandos, any outstanding references to the object point to the old element, etc. Example: jsbin.com/kucuf/1 In the normal case, your code above is effectively the same as var newElement = document.createElement(newName); newElement.innerHTML = element.innerHTML; element.parentNode.replaceChild(element, newElement);
@T.J.Crowder this seems like the best answer, but why didn't you just use replaceChild instead of the last insert and remove methods?
function changeTag(el, newTagName = "div") { var newEl = document.createElement(newTagName); [...el.children].forEach(o => newEl.appendChild(o)); [...el.attributes].forEach(o => newEl.attributes.setNamedItem(o.cloneNode())); el.parentNode.replaceChild(newEl, el); return newEl; }
wns.parentNode.replaceChild(lmn, wns) == wns.replaceWith(lmn). maybe its faster with wns.style.display = "none" to avoid onscreen repaints on lmn.appendChild(wns.firstChild)
|
27
var element = document.getElementById("93");
element.outerHTML = element.outerHTML.replace(/wns/g,"lmn");

FIDDLE

13 Comments

That's cool. Making the round-trip through markup will remove any event handlers on the descendant elements, though, which is less than ideal.
Amazing. I'd always thought outerHTML was a getter only, and couldn't be set. Revelatory!
Yeah but what if you have "wns" in the innerhtml of the tag?
If you have wns in content, it will be replaced. That's not funny.
Just use the full regex: Element.outerHTML = Element.outerHTML.replace(/^<wms(.*)wms>$/, "<lmn$1lmn>")
|
9

There are several problems with your code:

  1. HTML element IDs must start with an alphabetic character.
  2. document.getElementById("99").replace(/wns/g,"lmn") is effectively running a replace command on an element. Replace is a string method so this causes an error.
  3. You're trying to assign this result to document.getElementById("99").innerHTML, which is the HTML inside the element (the tags, attributes and all are part of the outerHTML).
  4. You can't change an element's tagname dynamically, since it fundamentally changes it's nature. Imagine changing a textarea to a select… There are so many attributes that are exclusive to one, illegal in the other: the system cannot work!

What you can do though, is create a new element, and give it all the properties of the old element, then replace it:

<wns id="e93" onclick="wish(id)">
    ...
</wns>

Using the following script:

// Grab the original element
var original    = document.getElementById('e93');
// Create a replacement tag of the desired type
var replacement = document.createElement('lmn');

// Grab all of the original's attributes, and pass them to the replacement
for(var i = 0, l = original.attributes.length; i < l; ++i){
    var nodeName  = original.attributes.item(i).nodeName;
    var nodeValue = original.attributes.item(i).nodeValue;

    replacement.setAttribute(nodeName, nodeValue);
}

// Persist contents
replacement.innerHTML = original.innerHTML;

// Switch!
original.parentNode.replaceChild(replacement, original);

Demo here: http://jsfiddle.net/barney/kDjuf/

Comments

1

[...document.querySelectorAll('.example')].forEach(div => {
  div.outerHTML =
  div.outerHTML
    .replace(/<div/g, '<span')
    .replace(/<\/div>/g, '</span>')
})
<div class="example">Hello,</div>
<div class="example">world!</div>

Comments

1

You can replace the whole tag using jQuery

var element = $('#99');
element.replaceWith($(`<lmn id="${element.attr('id')}">${element.html()}</lmn>`));

Comments

-2

You can achieve this by using JavaScript or jQuery.

We can delete the DOM Element(tag in this case) and recreate using .html or .append menthods in jQuery.

$("#div-name").html("<mytag>Content here</mytag>");

OR

$("<mytag>Content here</mytag>").appendTo("#div-name");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.