1'use strict';
2
3//Node construction
4exports.createDocument = function () {
5    return {
6        nodeName: '#document',
7        quirksMode: false,
8        childNodes: []
9    };
10};
11
12exports.createDocumentFragment = function () {
13    return {
14        nodeName: '#document-fragment',
15        quirksMode: false,
16        childNodes: []
17    };
18};
19
20exports.createElement = function (tagName, namespaceURI, attrs) {
21    return {
22        nodeName: tagName,
23        tagName: tagName,
24        attrs: attrs,
25        namespaceURI: namespaceURI,
26        childNodes: [],
27        parentNode: null
28    };
29};
30
31exports.createCommentNode = function (data) {
32    return {
33        nodeName: '#comment',
34        data: data,
35        parentNode: null
36    };
37};
38
39var createTextNode = function (value) {
40    return {
41        nodeName: '#text',
42        value: value,
43        parentNode: null
44    }
45};
46
47
48//Tree mutation
49exports.setDocumentType = function (document, name, publicId, systemId) {
50    var doctypeNode = null;
51
52    for (var i = 0; i < document.childNodes.length; i++) {
53        if (document.childNodes[i].nodeName === '#documentType') {
54            doctypeNode = document.childNodes[i];
55            break;
56        }
57    }
58
59    if (doctypeNode) {
60        doctypeNode.name = name;
61        doctypeNode.publicId = publicId;
62        doctypeNode.systemId = systemId;
63    }
64
65    else {
66        appendChild(document, {
67            nodeName: '#documentType',
68            name: name,
69            publicId: publicId,
70            systemId: systemId
71        });
72    }
73};
74
75exports.setQuirksMode = function (document) {
76    document.quirksMode = true;
77};
78
79exports.isQuirksMode = function (document) {
80    return document.quirksMode;
81};
82
83var appendChild = exports.appendChild = function (parentNode, newNode) {
84    parentNode.childNodes.push(newNode);
85    newNode.parentNode = parentNode;
86};
87
88var insertBefore = exports.insertBefore = function (parentNode, newNode, referenceNode) {
89    var insertionIdx = parentNode.childNodes.indexOf(referenceNode);
90
91    parentNode.childNodes.splice(insertionIdx, 0, newNode);
92    newNode.parentNode = parentNode;
93};
94
95exports.detachNode = function (node) {
96    if (node.parentNode) {
97        var idx = node.parentNode.childNodes.indexOf(node);
98
99        node.parentNode.childNodes.splice(idx, 1);
100        node.parentNode = null;
101    }
102};
103
104exports.insertText = function (parentNode, text) {
105    if (parentNode.childNodes.length) {
106        var prevNode = parentNode.childNodes[parentNode.childNodes.length - 1];
107
108        if (prevNode.nodeName === '#text') {
109            prevNode.value += text;
110            return;
111        }
112    }
113
114    appendChild(parentNode, createTextNode(text));
115};
116
117exports.insertTextBefore = function (parentNode, text, referenceNode) {
118    var prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
119
120    if (prevNode && prevNode.nodeName === '#text')
121        prevNode.value += text;
122    else
123        insertBefore(parentNode, createTextNode(text), referenceNode);
124};
125
126exports.adoptAttributes = function (recipientNode, attrs) {
127    var recipientAttrsMap = [];
128
129    for (var i = 0; i < recipientNode.attrs.length; i++)
130        recipientAttrsMap.push(recipientNode.attrs[i].name);
131
132    for (var j = 0; j < attrs.length; j++) {
133        if (recipientAttrsMap.indexOf(attrs[j].name) === -1)
134            recipientNode.attrs.push(attrs[j]);
135    }
136};
137
138
139//Tree traversing
140exports.getFirstChild = function (node) {
141    return node.childNodes[0];
142};
143
144exports.getChildNodes = function (node) {
145    return node.childNodes;
146};
147
148exports.getParentNode = function (node) {
149    return node.parentNode;
150};
151
152exports.getAttrList = function (node) {
153    return node.attrs;
154};
155
156//Node data
157exports.getTagName = function (element) {
158    return element.tagName;
159};
160
161exports.getNamespaceURI = function (element) {
162    return element.namespaceURI;
163};
164
165exports.getTextNodeContent = function (textNode) {
166    return textNode.value;
167};
168
169exports.getCommentNodeContent = function (commentNode) {
170    return commentNode.data;
171};
172
173exports.getDocumentTypeNodeName = function (doctypeNode) {
174    return doctypeNode.name;
175};
176
177exports.getDocumentTypeNodePublicId = function (doctypeNode) {
178    return doctypeNode.publicId;
179};
180
181exports.getDocumentTypeNodeSystemId = function (doctypeNode) {
182    return doctypeNode.systemId;
183};
184
185//Node types
186exports.isTextNode = function (node) {
187    return node.nodeName === '#text';
188};
189
190exports.isCommentNode = function (node) {
191    return node.nodeName === '#comment';
192};
193
194exports.isDocumentTypeNode = function (node) {
195    return node.nodeName === '#documentType';
196};
197
198exports.isElementNode = function (node) {
199    return !!node.tagName;
200};
201