X-Git-Url: https://git.mdrn.pl/fnpeditor.git/blobdiff_plain/f63769e206281f306f6c2cb937358837da450185..e32eab0:/src/smartxml/smartxml.js diff --git a/src/smartxml/smartxml.js b/src/smartxml/smartxml.js index 7d3f332..c158bac 100644 --- a/src/smartxml/smartxml.js +++ b/src/smartxml/smartxml.js @@ -4,24 +4,36 @@ define([ 'libs/backbone', 'smartxml/events', 'smartxml/transformations', - 'smartxml/core' -], function($, _, Backbone, events, transformations, coreTransformations) { + 'smartxml/core', + 'smartxml/fragments' +], function($, _, Backbone, events, transformations, coreTransformations, fragments) { 'use strict'; /* globals Node */ +var privateKey = '_smartxml'; + var DocumentNode = function(nativeNode, document) { if(!document) { throw new Error('undefined document for a node'); } this.document = document; + this.object = {}; this._setNativeNode(nativeNode); }; $.extend(DocumentNode.prototype, { + getProperty: function(propName) { + var toret = this.object[propName]; + if(toret && _.isFunction(toret)) { + toret = toret.call(this); + } + return toret; + }, + transform: function(Transformation, args) { var transformation = new Transformation(this.document, this, args); return this.document.transform(transformation); @@ -38,7 +50,7 @@ $.extend(DocumentNode.prototype, { clone.find('*').addBack().each(function() { var el = this, clonedData = $(this).data(); - + $(el).removeData(privateKey); _.pairs(clonedData).forEach(function(pair) { var key = pair[0], value = pair[1]; @@ -78,6 +90,14 @@ $.extend(DocumentNode.prototype, { return this.document.root.sameNode(this); }, + isInDocument: function() { + return this.document.containsNode(this); + }, + + isSiblingOf: function(node) { + return node && this.parent().sameNode(node.parent()); + }, + sameNode: function(otherNode) { return !!(otherNode) && this.nativeNode === otherNode.nativeNode; }, @@ -113,22 +133,27 @@ $.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); + isSurroundedByTextNodes: function() { + return this.isPrecededByTextNode() && this.isFollowedByTextNode(); + }, + + isPrecededByTextNode: function() { + var prev = this.prev(); + return prev && prev.nodeType === Node.TEXT_NODE; + }, + + isFollowedByTextNode: function() { + var next = this.next(); + return next && next.nodeType === Node.TEXT_NODE; }, triggerChangeEvent: function(type, metaData, origParent, nodeWasContained) { var node = (metaData && metaData.node) ? metaData.node : this, event = new events.ChangeEvent(type, $.extend({node: node}, metaData || {})); if(type === 'nodeDetached' || this.document.containsNode(event.meta.node)) { - if(type === 'nodeMoved') { - event.meta.parent = origParent; - } this.document.trigger('change', event); } - if((type === 'nodeAdded' || type === 'nodeMoved') && !this.document.containsNode(this) && nodeWasContained) { + if(type === 'nodeAdded' && !this.document.containsNode(this) && nodeWasContained) { event = new events.ChangeEvent('nodeDetached', {node: node, parent: origParent}); this.document.trigger('change', event); } @@ -139,28 +164,41 @@ $.extend(DocumentNode.prototype, { }, getIndex: function() { + var parent; + if(this.isRoot()) { return 0; } - return this.parent().indexOf(this); + + parent = this.parent(); + return parent ? parent.indexOf(this) : undefined; + }, + + getNearestElementNode: function() { + return this.nodeType === Node.ELEMENT_NODE ? this : this.parent(); } }); var ElementNode = function(nativeNode, document) { DocumentNode.call(this, nativeNode, document); + $(nativeNode).data(privateKey, {node: this}); }; ElementNode.prototype = Object.create(DocumentNode.prototype); $.extend(ElementNode.prototype, { nodeType: Node.ELEMENT_NODE, - setData: function(key, value) { - if(value !== undefined) { - this._$.data(key, value); + setData: function(arg1, arg2) { + if(arguments.length === 2) { + if(_.isUndefined(arg2)) { + this._$.removeData(arg1); + } else { + this._$.data(arg1, arg2); + } } else { this._$.removeData(_.keys(this._$.data())); - this._$.data(key); + this._$.data(arg1); } }, @@ -168,7 +206,9 @@ $.extend(ElementNode.prototype, { if(key) { return this._$.data(key); } - return this._$.data(); + var toret = _.clone(this._$.data()); + delete toret[privateKey]; + return toret; }, getTagName: function() { @@ -210,6 +250,32 @@ $.extend(ElementNode.prototype, { return node && (node.nativeNode === this.nativeNode || node._$.parents().index(this._$) !== -1); }, + getFirstTextNode: function() { + return this._getTextNode('first'); + }, + + getLastTextNode: function() { + return this._getTextNode('last'); + }, + + _getTextNode: function(which) { + var contents = this.contents(), + toret; + if(which === 'last') { + contents = contents.reverse(); + } + contents.some(function(node) { + if(node.nodeType === Node.TEXT_NODE) { + toret = node; + return true; + } + toret = node.getLastTextNode(); + return !!toret; + }); + + return toret; + }, + toXML: function() { var wrapper = $('