Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace Node Name

Is it possible to replace a nodes name? Like:

HTML:

<strong id="element">Text</strong>

Javascript:

var element = document.getElementById("element");
    element.nodeName = "b";

As I see it's not working, if it's not possible in this way, then how can it be done?

Why I need it:

I'm building a Text Editor, and IE uses strong instead of b in the execCommand() function and I would like to change that, I tried to build the execCommand("bold") from scratch but there is a lots of problem and differences even between IE 8 and 9. So now I decided to change it's node name, it would be really easy, but doesn't works.. :(

Note: I need this to work only in Internet Explorer.

Thanks

like image 328
Adam Halasz Avatar asked Nov 15 '25 05:11

Adam Halasz


2 Answers

No, but you can replace the node easily:

var oldNode = document.getElementById('element'),
    newNode = document.createElement('b'),
    node,
    nextNode;

node = oldNode.firstChild;
while (node) {
    nextNode = node.nextSibling;
    newNode.appendChild(node);
    node = nextNode;
}

newNode.className = oldNode.className;
// Do attributes too if you need to
newNode.id = oldNode.id; // (Not invalid, they're not both in the tree at the same time)
oldNode.parentNode.replaceChild(newNode, oldNode);

Live example

Many thanks to Haochi for pointing out replaceChild, I had done this:

oldNode.parentNode.insertBefore(newNode, oldNode);
oldNode.parentNode.removeChild(oldNode);

Live example ...but replaceChild is cleaner.

Docs:

  • DOM2 core
  • DOM2 HTML
  • DOM3 core
like image 130
T.J. Crowder Avatar answered Nov 17 '25 19:11

T.J. Crowder


Element.prototype.setTagName=function(strTN) {
 var oHTML=this.outerHTML, tempTag=document.createElement(strTN); //document.createElement will fire an error if string has wrong characters.
 var tName={original: this.tagName.toUpperCase(), change: strTN.toUpperCase()}
 if (tName.original == tName.change) return;
 oHTML=oHTML.replace(RegExp("(^\<" + tName.original + ")|(" + tName.original + "\>$)","gi"), function(x){return (x.toUpperCase().replace(tName.original, tName.change));});
 tempTag.innerHTML=oHTML;
 this.parentElement.replaceChild(tempTag.firstChild,this);
}

Use (in case you want to set a span for body's first element):

document.body.firstElementChild.setTagName("SPAN");

EDIT:

I forgot to mention something. It creates a new element so if you have the original one stored in a variable, the variable will be storing the old (unchanged) one. If the Element doesn't have a parent Element it fails.

That's why I made a new one:

Element.prototype.spawn = function(strTN = "spawn") {
 let tName = ({original: this.tagName.toUpperCase(), change: strTN.toUpperCase()}); if (tName.original == tName.change) { return; }
 let fragment = document.createRange().createContextualFragment(this.outerHTML.replace(new RegExp("(^\<\\b" + tName.original + "\\b)|(\\b" + tName.original + "\\b\>$)","gi"), function(x){return(x.toUpperCase().replace(tName.original, tName.change));}));
 return(fragment.firstChild);
}

This one just creates the new Element with all the original descendants but you have to place it to the DOM manually if you want:

var e = document.body.firstElementChild;
e.replaceWith(e.spawn("i"));
like image 39
t33st33r Avatar answered Nov 17 '25 20:11

t33st33r



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!