X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/7ceaca87e48317ad610b946192e0783885696f0d..72da90cac0feafb35cac9292105e24f2b5094b45:/src/smartxml/smartxml.js?ds=sidebyside diff --git a/src/smartxml/smartxml.js b/src/smartxml/smartxml.js index 1d9fdd0..0e05293 100644 --- a/src/smartxml/smartxml.js +++ b/src/smartxml/smartxml.js @@ -36,6 +36,30 @@ $.extend(DocumentNode.prototype, { this._$ = $(nativeNode); }, + clone: function() { + return this.document.createDocumentNode(this._$.clone(true, true)[0]); + }, + + getPath: function(ancestor) { + var nodePath = [this].concat(this.parents()), + toret, idx; + ancestor = ancestor || this.document.root; + + nodePath.some(function(node, i) { + if(node.sameNode(ancestor)) { + idx = i; + return true; + } + }); + + if(idx !== 'undefined') { + nodePath = nodePath.slice(0, idx); + } + toret = nodePath.map(function(node) {return node.getIndex(); }); + toret.reverse(); + return toret; + }, + isRoot: function() { return this.document.root.sameNode(this); }, @@ -54,7 +78,7 @@ $.extend(DocumentNode.prototype, { parent: function() { var parentNode = this.nativeNode.parentNode; if(parentNode && parentNode.nodeType === Node.ELEMENT_NODE) { - return this.document.createElementNode(parentNode); + return this.document.createDocumentNode(parentNode); } return null; }, @@ -82,6 +106,12 @@ $.extend(DocumentNode.prototype, { return myIdx < parentContents.length - 1 ? parentContents[myIdx+1] : null; }, + isSurroundedByTextElements: function() { + var prev = this.prev(), + next = this.next(); + return prev && (prev.nodeType === Node.TEXT_NODE) && next && (next.nodeType === Node.TEXT_NODE); + }, + after: INSERTION(function(nativeNode) { return this._$.after(nativeNode); }), @@ -128,7 +158,7 @@ $.extend(DocumentNode.prototype, { insertion.ofNode = node; insertion.insertsNew = !this.document.containsNode(node); } else { - insertion.ofNode = this.document.createElementNode(node); + insertion.ofNode = this.document.createDocumentNode(node); insertion.insertsNew = true; } return insertion; @@ -151,13 +181,11 @@ $.extend(ElementNode.prototype, { nodeType: Node.ELEMENT_NODE, detach: function() { - var prev = this.prev(), + var next; + if(parent && this.isSurroundedByTextElements()) { next = this.next(); - if(parent) { - if(prev && prev.nodeType === Node.TEXT_NODE && next && next.nodeType === Node.TEXT_NODE) { - prev.appendText(next.getText()); - next.detach(); - } + this.prev().appendText(next.getText()); + next.detach(); } return DocumentNode.prototype.detach.call(this); }, @@ -186,12 +214,7 @@ $.extend(ElementNode.prototype, { var toret = [], document = this.document; this._$.contents().each(function() { - if(this.nodeType === Node.ELEMENT_NODE) { - toret.push(document.createElementNode(this)); - } - else if(this.nodeType === Node.TEXT_NODE) { - toret.push(document.createTextNode(this)); - } + toret.push(document.createDocumentNode(this)); }); return toret; }, @@ -201,7 +224,7 @@ $.extend(ElementNode.prototype, { }, setTag: function(tagName) { - var node = this.document.createElementNode({tagName: tagName}), + var node = this.document.createDocumentNode({tagName: tagName}), oldTagName = this.getTagName(), myContents = this._$.contents(); @@ -352,6 +375,44 @@ $.extend(TextNode.prototype, { } }, + split: function(params) { + var parentElement = this.parent(), + passed = false, + succeedingChildren = [], + prefix = this.getText().substr(0, params.offset), + suffix = this.getText().substr(params.offset); + + parentElement.contents().forEach(function(child) { + if(passed) { + succeedingChildren.push(child); + } + if(child.sameNode(this)) { + passed = true; + } + }.bind(this)); + + if(prefix.length > 0) { + this.setText(prefix); + } + else { + this.detach(); + } + + var attrs = {}; + parentElement.getAttrs().forEach(function(attr) {attrs[attr.name] = attr.value; }); + var newElement = this.document.createDocumentNode({tagName: parentElement.getTagName(), attrs: attrs}); + parentElement.after(newElement); + + if(suffix.length > 0) { + newElement.append({text: suffix}); + } + succeedingChildren.forEach(function(child) { + newElement.append(child); + }); + + return {first: parentElement, second: newElement}; + }, + triggerTextChangeEvent: function() { var event = new events.ChangeEvent('nodeTextChange', {node: this}); this.document.trigger('change', event); @@ -360,7 +421,7 @@ $.extend(TextNode.prototype, { var parseXML = function(xml) { - return $(xml)[0]; + return $($.trim(xml))[0]; }; var Document = function(xml) { @@ -371,9 +432,9 @@ $.extend(Document.prototype, Backbone.Events, { ElementNodeFactory: ElementNode, TextNodeFactory: TextNode, - createElementNode: function(from) { - if(!(from instanceof HTMLElement)) { - if(from.text) { + createDocumentNode: function(from) { + if(!(from instanceof Node)) { + if(from.text !== undefined) { from = document.createTextNode(from.text); } else { var node = $('<' + from.tagName + '>'); @@ -394,10 +455,6 @@ $.extend(Document.prototype, Backbone.Events, { return new Factory(from, this); }, - createTextNode: function(nativeNode) { - return new this.TextNodeFactory(nativeNode, this); - }, - loadXML: function(xml, options) { options = options || {}; defineDocumentProperties(this, $(parseXML(xml))); @@ -421,7 +478,7 @@ $.extend(Document.prototype, Backbone.Events, { var parent = params.element1.parent(), parentContents = parent.contents(), - wrapper = this.createElementNode({ + wrapper = this.createDocumentNode({ tagName: params._with.tagName, attrs: params._with.attrs}), idx1 = parent.indexOf(params.element1), @@ -491,7 +548,7 @@ $.extend(Document.prototype, Backbone.Events, { throw new Error('Wrapping text in non-sibling text nodes not supported.'); } - var wrapperElement = this.createElementNode({tagName: params._with.tagName, attrs: params._with.attrs}); + var wrapperElement = this.createDocumentNode({tagName: params._with.tagName, attrs: params._with.attrs}); textNode1.after(wrapperElement); textNode1.detach(); @@ -527,7 +584,7 @@ $.extend(Document.prototype, Backbone.Events, { var defineDocumentProperties = function(doc, $document) { Object.defineProperty(doc, 'root', {get: function() { - return doc.createElementNode($document[0]); + return doc.createDocumentNode($document[0]); }, configurable: true}); Object.defineProperty(doc, 'dom', {get: function() { return $document[0]; @@ -536,7 +593,7 @@ var defineDocumentProperties = function(doc, $document) { return { documentFromXML: function(xml) { - return new Document(parseXML(xml)); + return new Document(xml); }, elementNodeFromXML: function(xml) {