smartxml: allow objects set with setData to clone themselves on node cloning
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Thu, 16 Jan 2014 09:34:31 +0000 (10:34 +0100)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Thu, 16 Jan 2014 09:34:31 +0000 (10:34 +0100)
src/smartxml/smartxml.js
src/smartxml/smartxml.test.js

index acbe04d..000f722 100644 (file)
@@ -34,6 +34,16 @@ $.extend(DocumentNode.prototype, {
 
     clone: function() {
         var clone = this._$.clone(true, true);
+        clone.find('*').addBack().each(function() {
+            var clonedData = $(this).data();
+            _.pairs(clonedData).forEach(function(pair) {
+                var key = pair[0],
+                    value = pair[1];
+                if(_.isFunction(value.clone)) {
+                    clonedData[key] = value.clone();
+                }
+            });
+        });
         return this.document.createDocumentNode(clone[0]);
     },
 
index 57f11cc..0883ba7 100644 (file)
@@ -86,6 +86,31 @@ describe('smartxml', function() {
             });
         });
 
+        it('can be cloned with its contents and its contents data', function() {
+            var doc = getDocumentFromXML('<root><div></div></root>'),
+                root = doc.root,
+                div = root.contents()[0];
+
+            var ClonableObject = function(arg) {
+                this.arg = arg;
+            };
+            ClonableObject.prototype.clone = function() {
+                return new ClonableObject(this.arg);
+            };
+
+            div.setData('key', 'value');
+            div.setData('clonableObject', new ClonableObject('test'));
+
+            var rootClone = root.clone(),
+                divClone = rootClone.contents()[0],
+                stringClone = divClone.getData('key'),
+                objClone = divClone.getData('clonableObject');
+
+            expect(stringClone).to.equal('value');
+            expect(objClone.arg).to.equal('test', 'clonable object got copied');
+            expect(objClone !== div.getData('clonableObject')).to.be.equal(true, 'copy of the clonable object is a new object');
+        });
+
         it('knows its path in the document tree', function() {
             var doc = getDocumentFromXML('<root><a><b><c></c>text</b></a></root>'),
                 root = doc.root,