If you use cloneNode() or removeChild() when writing javascript, be aware that they are both broken. very broken
From the W3C DOM Level 2 specification of cloneNode() (emphasis mine)
cloneNode()Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. [...] Cloning an Element copies all attributes and their values, those generated by the XML processor to represent defaulted attributes ...
If only it were so. Problem is that when you clone a node from the DOM tree in Internet Explorer any changes to that node after page load are not cloned. This is true even when you do a deep-copy clone.
I've created an example page that shows that even a simple action like checking a checkbox will not be reflected on a cloned copy.
That hurts. Now as javascript developers we have to implement our own cloneNode methods to do what Internet Explorer should have been doing all along.
But it gets worse, not only does cloneNode suffer from amnesia, the same problems happen when you even remove a node from the DOM tree and immediately add it back in. It looses attributes. Thats bad. real bad.
Again quoting the W3C DOM Level 2 specification on removeChild()
removeChild(oldChild)Removes the child node indicated by oldChild from the list of children, and returns it.
Say you want to move an element from one section of the page to another
That all looks straight forward enough.. right? Problem is that as soon as you call removeChild it looses attributes. If it's a check box that was checked before, now it's just a checkbox. Thats bad as well. real bad
The DOM specification above certainly didn't say anything about changing attributes when you use it. It said it would return the node, not something similar to the node.
No problem the removeChild part is actually optional in this usage, that happens automatically when you appendChild right? not to be fooled, the same problem persists if you just use appendChild() to insert it in the same place without removing it first. attributes are lost.
Here is an example page showing this problem as well
what to do?
I wish I knew. If you have thoughts about this please leave them below
3 years, 11 months ago
I don’t think IE necessarily has a broken implementation of either of these methods. I think it’s appendNode that does. For example, create a checkbox node, check it, and then insert it into the page. It won’t be checked.
i.type=”checkbox”;
i.checked = true;
document.getElementById(“whatever”).appendChild(i);
And not all glass is clear.
3 years, 5 months ago
the events are cloned too when using IE if you use the “attachEvent” method to attache an event on the element being cloned
2 years, 2 months ago
Could you update this with an alternative please? I just found this on google searching for “removeChild problem” and didn’t find this that helpful.
2 years, 1 month ago
Same as Dan here. Searched at google and found this here. But it wasn’t realy helpful.
2 years ago
Here is another example regarding this. This caused me many headaches. I’ve found the best way is to just take the HTML using innerHTML and then appending it to a new Node that you create.
http://javascript-today.blogspot.com/2008/07/clonenode-problem.html
Mike
1 year, 9 months ago
[...] cloneNode() and removeChild() are broken cloneNode() Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. […] Cloning an Element copies all attributes and their values, those generated by the XML processor to represent defaulted attributes … (tags: jehiah.cz 2008 mes9 dia30 cloneNode removeChild DOM JavaScript) [...]
1 year, 5 months ago
“Problem is that when you clone a node from the DOM tree in Internet Explorer any changes to that node after page load are not cloned”
Not true. Please correct or remove this article because it not helpful.
(You are right about the checkbox issue, but this is the only true part of the article. You need to set also defaultChecked property for a checkbox when you are adding it to the dom tree in ie.)
1 year, 5 months ago
Just tested your “example page”.
If you change your code in onload, like:
document.getElementById(“targetElement”).checked = document.getElementById(“targetElement”).defaultChecked = true;
Now the example works fine in ie.
Unfortunately your original example yields to a total wrong conclusion… ;)