8 var TEXT_NODE = Node.TEXT_NODE, ELEMENT_NODE = Node.ELEMENT_NODE;
10 var parseXML = function(xml) {
14 var Document = function(nativeNode) {
15 var $document = $(nativeNode);
18 Object.defineProperty(this, 'root', {get: function() { return new ElementNode($document[0]);}});
22 var DocumentNode = function(nativeNode) {
23 this.nativeNode = nativeNode;
24 this._$ = $(nativeNode);
27 $.extend(DocumentNode.prototype, {
28 detach: function() { this._$.detach(); },
30 sameNode: function(otherNode) {
31 return this.nativeNode === otherNode.nativeNode;
35 var ElementNode = function(nativeNode) {
36 DocumentNode.apply(this, arguments);
39 $.extend(ElementNode.prototype, DocumentNode.prototype, {
40 nodeType: Node.ELEMENT_NODE,
42 getTagName: function() {
43 return this.nativeNode.tagName.toLowerCase();
46 contents: function() {
48 this._$.contents().each(function() {
49 if(this.nodeType === Node.ELEMENT_NODE)
50 toret.push(new ElementNode(this));
51 else if(this.nodeType === Node.TEXT_NODE)
52 toret.push(new TextNode(this));
57 indexOf: function(node) {
58 return this._$.contents().index(node._$);
62 return new ElementNode(this._$.parent());
65 append: function(documentNode) {
66 this._$.append(documentNode.nativeNode);
69 before: function(node) {
70 this._$.before(node.nativeNode);
73 unwrapContent: function() {
74 var parent = this.parent();
78 var parentContents = parent.contents(),
79 myContents = this.contents(),
80 myIdx = parent.indexOf(this);
82 if(myContents.length === 0)
85 var moveLeftRange, moveRightRange, leftMerged;
87 if(myIdx > 0 && (parentContents[myIdx-1].nodeType === TEXT_NODE) && (myContents[0].nodeType === TEXT_NODE)) {
88 parentContents[myIdx-1].appendText(myContents[0].getText());
89 myContents[0].detach();
96 if(!(leftMerged && myContents.length === 1)) {
97 if(myIdx < parentContents.length - 1 && (parentContents[myIdx+1].nodeType === TEXT_NODE) && (myContents[myContents.length-1].nodeType === TEXT_NODE)) {
98 parentContents[myIdx+1].prependText(myContents[myContents.length-1].getText());
99 myContents[myContents.length-1].detach();
100 moveRightRange = true;
104 var childrenLength = this.contents().length;
105 this.contents().forEach(function(child) {
112 element1: parent.contents()[myIdx + (moveLeftRange ? -1 : 0)],
113 element2: parent.contents()[myIdx + childrenLength-1 + (moveRightRange ? 1 : 0)]
119 var TextNode = function(nativeNode) {
120 DocumentNode.apply(this, arguments);
123 $.extend(TextNode.prototype, DocumentNode.prototype, {
124 nodeType: Node.TEXT_NODE,
126 getText: function() {
127 return this.nativeNode.data;
130 appendText: function(text) {
131 this.nativeNode.data = this.nativeNode.data + text;
134 prependText: function(text) {
135 this.nativeNode.data = text + this.nativeNode.data;
141 documentFromXML: function(xml) {
142 return new Document(parseXML(xml));
145 elementNodeFromXML: function(xml) {
146 return new ElementNode(parseXML(xml));