smartxml: removing special implementation for changing tag name
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Thu, 13 Mar 2014 09:39:36 +0000 (10:39 +0100)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Fri, 28 Mar 2014 12:23:26 +0000 (13:23 +0100)
NodeElement.setTag stops being a magic method that tries to simulate
tagName as being a mutable property. It's now just a shortcut for
replaceWith combined with copying replaced element contents, attributes
and custom data. This change:

- allows for removal of a separate nodeTagChange event,
- simplifies implementation,
- makes api more in line with DOM specification,
- invalidates references to the old node explicitly by returning
reference to a newly created node.

src/smartxml/core.js
src/smartxml/smartxml.test.js

index a2d39a6..9630a77 100644 (file)
@@ -115,26 +115,21 @@ var elementNodeTransformations = {
     },
 
     setTag: function(tagName) {
     },
 
     setTag: function(tagName) {
-        var node = this.document.createDocumentNode({tagName: tagName}),
-            oldTagName = this.getTagName(),
-            myContents = this._$.contents();
+        var node = this.document.createDocumentNode({tagName: tagName});
 
         this.getAttrs().forEach(function(attribute) {
 
         this.getAttrs().forEach(function(attribute) {
-            node.setAttr(attribute.name, attribute.value, true);
+            node.setAttr(attribute.name, attribute.value);
         });
         });
-        node.setData(this.getData());
 
 
-        if(this.sameNode(this.document.root)) {
-            this.document._defineDocumentProperties(node._$);
-        }
+        this.contents().forEach(function(child) {
+            node.append(child);
+        });
 
 
-        /* TODO: This invalidates old references to this node. Caching instances on nodes would fix this. */
-        this._$.replaceWith(node._$);
-        this._setNativeNode(node._$[0]);
-        this._$.append(myContents);
-        this.triggerChangeEvent('nodeTagChange', {oldTagName: oldTagName, newTagName: this.getTagName()});
-    },
+        node.setData(this.getData());
 
 
+        this.replaceWith(node);
+        return node;
+    },
 
     setAttr: function(name, value, silent) {
         var oldVal = this.getAttr(name);
 
     setAttr: function(name, value, silent) {
         var oldVal = this.getAttr(name);
index fb420db..e4e2724 100644 (file)
@@ -169,40 +169,16 @@ describe('smartxml', function() {
 
             it('can change tag name', function() {
                 var node = elementNodeFromXML('<div></div>');
 
             it('can change tag name', function() {
                 var node = elementNodeFromXML('<div></div>');
-                node.setTag('span');
+                node = node.setTag('span');
                 expect(node.getTagName()).to.equal('span');
             });
 
                 expect(node.getTagName()).to.equal('span');
             });
 
-            it('emits nodeTagChange event', function() {
-                var node = elementNodeFromXML('<div></div>'),
-                    spy = sinon.spy();
-
-                node.document.on('change', spy);
-                node.setTag('span');
-                var event = spy.args[0][0];
-
-                expect(event.type).to.equal('nodeTagChange');
-                expect(event.meta.node.sameNode(node)).to.be.true;
-                expect(event.meta.oldTagName).to.equal('div');
-            });
-
             describe('Implementation specific expectations', function() {
             describe('Implementation specific expectations', function() {
-                // DOM specifies ElementNode tag as a read-only property, so
-                // changing it in a seamless way is a little bit tricky. For this reason
-                // the folowing expectations are required, despite the fact that they actually are
-                // motivated by implemetation details.
-
-                it('keeps node in the document', function() {
-                    var doc = getDocumentFromXML('<div><header></header></div>'),
-                        header = doc.root.contents()[0];
-                    header.setTag('span');
-                    expect(header.parent().sameNode(doc.root)).to.be.true;
-                });
                 it('keeps custom data', function() {
                     var node = elementNodeFromXML('<div></div>');
 
                     node.setData('key', 'value');
                 it('keeps custom data', function() {
                     var node = elementNodeFromXML('<div></div>');
 
                     node.setData('key', 'value');
-                    node.setTag('header');
+                    node = node.setTag('header');
                     
                     expect(node.getTagName()).to.equal('header');
                     expect(node.getData()).to.eql({key: 'value'});
                     
                     expect(node.getTagName()).to.equal('header');
                     expect(node.getData()).to.eql({key: 'value'});
@@ -214,9 +190,9 @@ describe('smartxml', function() {
                     expect(doc.root.getTagName()).to.equal('span');
                 });
 
                     expect(doc.root.getTagName()).to.equal('span');
                 });
 
-                it('keeps contents', function() {
+                it('keeps node contents', function() {
                     var node = elementNodeFromXML('<div><div></div></div>');
                     var node = elementNodeFromXML('<div><div></div></div>');
-                    node.setTag('header');
+                    node = node.setTag('header');
                     expect(node.contents()).to.have.length(1);
                 });
             });
                     expect(node.contents()).to.have.length(1);
                 });
             });