X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/f291310bd26717330272d1be30e4a5b935220ce8..cef69fff5322bdc7766d7063809694f6ee0e9e47:/src/smartxml/core.js diff --git a/src/smartxml/core.js b/src/smartxml/core.js index a2d39a6..b40e9c3 100644 --- a/src/smartxml/core.js +++ b/src/smartxml/core.js @@ -13,12 +13,21 @@ var INSERTION = function(implementation) { nodeParent, returned; options = options || {}; - if(!(this.document.containsNode(this)) || !insertion.isNew) { + if(!(this.document.containsNode(this)) || !insertion.insertsNew) { nodeParent = insertion.ofNode.parent(); } + if(!insertion.insertsNew && insertion.ofNode.isSurroundedByTextNodes()) { + var prev = insertion.ofNode.prev(), + next = insertion.ofNode.next(); + prev.setText(prev.getText()+next.getText()); + next.detach(); + } returned = implementation.call(this, insertion.ofNode); - if(!options.silent && returned.sameNode(insertion.ofNode)) { - this.triggerChangeEvent(insertion.insertsNew ? 'nodeAdded' : 'nodeMoved', {node: insertion.ofNode}, nodeParent, nodeWasContained); + if(!options.silent && returned && returned.sameNode(insertion.ofNode)) { + if(!insertion.insertsNew) { + this.triggerChangeEvent('nodeDetached', {node: insertion.ofNode, parent: nodeParent, move: true}); + } + this.triggerChangeEvent('nodeAdded', {node: insertion.ofNode, move: !insertion.insertsNew}, nodeParent, nodeWasContained); } return returned; }; @@ -54,7 +63,11 @@ var documentNodeTransformations = { }, after: INSERTION(function(node) { + if(this.isRoot()) { + return; + } var next = this.next(); + if(next && next.nodeType === Node.TEXT_NODE && node.nodeType === Node.TEXT_NODE) { next.setText(node.getText() + next.getText()); node.detach(); @@ -65,6 +78,9 @@ var documentNodeTransformations = { }), before: INSERTION(function(node) { + if(this.isRoot()) { + return; + } var prev = this.prev(); if(prev && prev.nodeType === Node.TEXT_NODE && node.nodeType === Node.TEXT_NODE) { prev.setText(prev.getText() + node.getText()); @@ -104,37 +120,44 @@ var documentNodeTransformations = { var elementNodeTransformations = { - detach: function() { + detach: function(params) { var next; - if(this.parent() && this.isSurroundedByTextElements()) { - next = this.next(); - this.prev().appendText(next.getText()); - next.detach(); + params = _.extend({ + normalizeStrategy: 'merge' + }, params); + + if(this.parent() && this.isSurroundedByTextNodes()) { + if(params.normalizeStrategy === 'detach-left') { + this.prev().detach(); + } else if(params.normalizeStrategy === 'detach-right') { + this.next().detach(); + } else if(params.normalizeStrategy === 'merge') { + next = this.next(); + this.prev().appendText(next.getText()); + next.detach(); + } else { + throw new Error('unknown normalize strategy for detach'); + } } return this.__super__.detach(); }, 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) { - 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); @@ -183,15 +206,21 @@ var elementNodeTransformations = { return; } + this.contents() + .filter(function(child) { + return child.getProperty('describesParent'); + }.bind(this)) + .forEach(function(child) { + child.detach(); + }); + var myContents = this.contents(), myIdx = parent.indexOf(this); - if(myContents.length === 0) { return this.detach(); } - var childrenLength = this.contents().length, first = true, shiftRange = false; @@ -315,12 +344,12 @@ var textNodeTransformations = { var newElement = this.document.createDocumentNode({tagName: parentElement.getTagName(), attrs: attrs}); parentElement.after(newElement); + succeedingChildren.reverse().forEach(function(child) { + newElement.prepend(child); + }); if(suffix.length > 0) { - newElement.append({text: suffix}); + newElement.prepend({text: suffix}); } - succeedingChildren.forEach(function(child) { - newElement.append(child); - }); return {first: parentElement, second: newElement}; }, @@ -377,7 +406,9 @@ var documentTransformations = { } for(var i = idx1; i <= idx2; i++) { - wrapper.append(parentContents[i].detach()); + if(!parentContents[i].getProperty('describesParent')) { + wrapper.append(parentContents[i].detach()); + } } insertingTarget[insertingMethod](wrapper); @@ -422,7 +453,9 @@ var documentTransformations = { wrapperElement.append({text: prefixInside}); } for(var i = idx1 + 1; i < idx2; i++) { - wrapperElement.append(contentsInside[i]); + if(!contentsInside[i].getProperty('describesParent')) { + wrapperElement.append(contentsInside[i]); + } } if(suffixInside.length > 0) { wrapperElement.append({text: suffixInside});