Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does cloneNode exclude custom properties?

This is related to the question javascript cloneNode and properties.

I'm seeing the same behaviour. Node.cloneNode does not copy over any properties that I add myself (code from original post):

    var theSource = document.getElementById("someDiv")
    theSource.dictator = "stalin";

    var theClone = theSource.cloneNode(true);
    alert(theClone.dictator); 

theClone does not contain any property "dictator".

I haven't been able to find any explanation for why this is the case. The documentation on MDN states that cloneNode "copies all of its attributes and their values", a line which is taken directly from the DOM specification itself.

This seems broken to me as it makes it next to impossible to do a deep copy of a DOM tree that contains custom properties.

Am I missing something here?

like image 599
Scott Cameron Avatar asked Aug 07 '12 21:08

Scott Cameron


Video Answer


3 Answers

A property is not equal to an attribute.

Use setAttribute() and getAttribute() instead.

var theSource = document.getElementById("someDiv")
theSource.setAttribute('dictator','stalin');

var theClone = theSource.cloneNode(true);
alert(theClone.getAttribute('dictator')); 
like image 188
Dr.Molle Avatar answered Nov 15 '22 01:11

Dr.Molle


Not every property corresponds to an attribute. Adding a custom property to an element does not add an attribute, so what happens when you do that is not covered by the DOM spec.

In fact, what happens when you add a property to a host object (such as a DOM node) is completely unspecified and is by no means guaranteed to work, so I'd strongly recommend against doing it. Instead, I'd suggest using wrappers if you want to extend the functionality of host objects (as jQuery and many other libraries do).

like image 20
Tim Down Avatar answered Nov 14 '22 23:11

Tim Down


Tested this. cloneNode does include the custom attribute in the clone, but that attribute can't be retrieved directly. Try:

 var theSource = document.getElementById("someDiv")
 theSource.dictator = "stalin";
 //or better / more cross browser compatible
 theSource.setAttribute('dictator','stalin');

 var theClone = theSource.cloneNode(true);
 alert(theClone.getAttribute('dictator')); //so, use getAttribute 

It may be a browser problem with cloning expando properties. I ran a testcase (see later) from this rather old bugzilla report. It didn't work in Chrome and Firefox (both latest versions).

//code from testcase @ bugzilla
var a = document.createElement("div");      
a.order = 50;      
alert(a.order);      
b = a.cloneNode(true);      
alert(b.order);    
like image 38
KooiInc Avatar answered Nov 15 '22 01:11

KooiInc