'use strict'; //Node construction exports.createDocument = function () { return { nodeName: '#document', quirksMode: false, childNodes: [] }; }; exports.createDocumentFragment = function () { return { nodeName: '#document-fragment', quirksMode: false, childNodes: [] }; }; exports.createElement = function (tagName, namespaceURI, attrs) { return { nodeName: tagName, tagName: tagName, attrs: attrs, namespaceURI: namespaceURI, childNodes: [], parentNode: null }; }; exports.createCommentNode = function (data) { return { nodeName: '#comment', data: data, parentNode: null }; }; var createTextNode = function (value) { return { nodeName: '#text', value: value, parentNode: null } }; //Tree mutation exports.setDocumentType = function (document, name, publicId, systemId) { var doctypeNode = null; for (var i = 0; i < document.childNodes.length; i++) { if (document.childNodes[i].nodeName === '#documentType') { doctypeNode = document.childNodes[i]; break; } } if (doctypeNode) { doctypeNode.name = name; doctypeNode.publicId = publicId; doctypeNode.systemId = systemId; } else { appendChild(document, { nodeName: '#documentType', name: name, publicId: publicId, systemId: systemId }); } }; exports.setQuirksMode = function (document) { document.quirksMode = true; }; exports.isQuirksMode = function (document) { return document.quirksMode; }; var appendChild = exports.appendChild = function (parentNode, newNode) { parentNode.childNodes.push(newNode); newNode.parentNode = parentNode; }; var insertBefore = exports.insertBefore = function (parentNode, newNode, referenceNode) { var insertionIdx = parentNode.childNodes.indexOf(referenceNode); parentNode.childNodes.splice(insertionIdx, 0, newNode); newNode.parentNode = parentNode; }; exports.detachNode = function (node) { if (node.parentNode) { var idx = node.parentNode.childNodes.indexOf(node); node.parentNode.childNodes.splice(idx, 1); node.parentNode = null; } }; exports.insertText = function (parentNode, text) { if (parentNode.childNodes.length) { var prevNode = parentNode.childNodes[parentNode.childNodes.length - 1]; if (prevNode.nodeName === '#text') { prevNode.value += text; return; } } appendChild(parentNode, createTextNode(text)); }; exports.insertTextBefore = function (parentNode, text, referenceNode) { var prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1]; if (prevNode && prevNode.nodeName === '#text') prevNode.value += text; else insertBefore(parentNode, createTextNode(text), referenceNode); }; exports.adoptAttributes = function (recipientNode, attrs) { var recipientAttrsMap = []; for (var i = 0; i < recipientNode.attrs.length; i++) recipientAttrsMap.push(recipientNode.attrs[i].name); for (var j = 0; j < attrs.length; j++) { if (recipientAttrsMap.indexOf(attrs[j].name) === -1) recipientNode.attrs.push(attrs[j]); } }; //Tree traversing exports.getFirstChild = function (node) { return node.childNodes[0]; }; exports.getChildNodes = function (node) { return node.childNodes; }; exports.getParentNode = function (node) { return node.parentNode; }; exports.getAttrList = function (node) { return node.attrs; }; //Node data exports.getTagName = function (element) { return element.tagName; }; exports.getNamespaceURI = function (element) { return element.namespaceURI; }; exports.getTextNodeContent = function (textNode) { return textNode.value; }; exports.getCommentNodeContent = function (commentNode) { return commentNode.data; }; exports.getDocumentTypeNodeName = function (doctypeNode) { return doctypeNode.name; }; exports.getDocumentTypeNodePublicId = function (doctypeNode) { return doctypeNode.publicId; }; exports.getDocumentTypeNodeSystemId = function (doctypeNode) { return doctypeNode.systemId; }; //Node types exports.isTextNode = function (node) { return node.nodeName === '#text'; }; exports.isCommentNode = function (node) { return node.nodeName === '#comment'; }; exports.isDocumentTypeNode = function (node) { return node.nodeName === '#documentType'; }; exports.isElementNode = function (node) { return !!node.tagName; };