var domWalk = require("dom-walk") var dispatchEvent = require("./event/dispatch-event.js") var addEventListener = require("./event/add-event-listener.js") var removeEventListener = require("./event/remove-event-listener.js") var serializeNode = require("./serialize.js") var htmlns = "http://www.w3.org/1999/xhtml" module.exports = DOMElement function DOMElement(tagName, owner, namespace) { if (!(this instanceof DOMElement)) { return new DOMElement(tagName) } var ns = namespace === undefined ? htmlns : (namespace || null) this.tagName = ns === htmlns ? String(tagName).toUpperCase() : tagName this.nodeName = this.tagName this.className = "" this.dataset = {} this.childNodes = [] this.parentNode = null this.style = {} this.ownerDocument = owner || null this.namespaceURI = ns this._attributes = {} if (this.tagName === 'INPUT') { this.type = 'text' } } DOMElement.prototype.type = "DOMElement" DOMElement.prototype.nodeType = 1 DOMElement.prototype.appendChild = function _Element_appendChild(child) { if (child.parentNode) { child.parentNode.removeChild(child) } this.childNodes.push(child) child.parentNode = this return child } DOMElement.prototype.replaceChild = function _Element_replaceChild(elem, needle) { // TODO: Throw NotFoundError if needle.parentNode !== this if (elem.parentNode) { elem.parentNode.removeChild(elem) } var index = this.childNodes.indexOf(needle) needle.parentNode = null this.childNodes[index] = elem elem.parentNode = this return needle } DOMElement.prototype.removeChild = function _Element_removeChild(elem) { // TODO: Throw NotFoundError if elem.parentNode !== this var index = this.childNodes.indexOf(elem) this.childNodes.splice(index, 1) elem.parentNode = null return elem } DOMElement.prototype.insertBefore = function _Element_insertBefore(elem, needle) { // TODO: Throw NotFoundError if referenceElement is a dom node // and parentNode !== this if (elem.parentNode) { elem.parentNode.removeChild(elem) } var index = needle === null || needle === undefined ? -1 : this.childNodes.indexOf(needle) if (index > -1) { this.childNodes.splice(index, 0, elem) } else { this.childNodes.push(elem) } elem.parentNode = this return elem } DOMElement.prototype.setAttributeNS = function _Element_setAttributeNS(namespace, name, value) { var prefix = null var localName = name var colonPosition = name.indexOf(":") if (colonPosition > -1) { prefix = name.substr(0, colonPosition) localName = name.substr(colonPosition + 1) } if (this.tagName === 'INPUT' && name === 'type') { this.type = value; } else { var attributes = this._attributes[namespace] || (this._attributes[namespace] = {}) attributes[localName] = {value: value, prefix: prefix} } } DOMElement.prototype.getAttributeNS = function _Element_getAttributeNS(namespace, name) { var attributes = this._attributes[namespace]; var value = attributes && attributes[name] && attributes[name].value if (this.tagName === 'INPUT' && name === 'type') { return this.type; } if (typeof value !== "string") { return null } return value } DOMElement.prototype.removeAttributeNS = function _Element_removeAttributeNS(namespace, name) { var attributes = this._attributes[namespace]; if (attributes) { delete attributes[name] } } DOMElement.prototype.hasAttributeNS = function _Element_hasAttributeNS(namespace, name) { var attributes = this._attributes[namespace] return !!attributes && name in attributes; } DOMElement.prototype.setAttribute = function _Element_setAttribute(name, value) { return this.setAttributeNS(null, name, value) } DOMElement.prototype.getAttribute = function _Element_getAttribute(name) { return this.getAttributeNS(null, name) } DOMElement.prototype.removeAttribute = function _Element_removeAttribute(name) { return this.removeAttributeNS(null, name) } DOMElement.prototype.hasAttribute = function _Element_hasAttribute(name) { return this.hasAttributeNS(null, name) } DOMElement.prototype.removeEventListener = removeEventListener DOMElement.prototype.addEventListener = addEventListener DOMElement.prototype.dispatchEvent = dispatchEvent // Un-implemented DOMElement.prototype.focus = function _Element_focus() { return void 0 } DOMElement.prototype.toString = function _Element_toString() { return serializeNode(this) } DOMElement.prototype.getElementsByClassName = function _Element_getElementsByClassName(classNames) { var classes = classNames.split(" "); var elems = [] domWalk(this, function (node) { if (node.nodeType === 1) { var nodeClassName = node.className || "" var nodeClasses = nodeClassName.split(" ") if (classes.every(function (item) { return nodeClasses.indexOf(item) !== -1 })) { elems.push(node) } } }) return elems } DOMElement.prototype.getElementsByTagName = function _Element_getElementsByTagName(tagName) { tagName = tagName.toLowerCase() var elems = [] domWalk(this.childNodes, function (node) { if (node.nodeType === 1 && (tagName === '*' || node.tagName.toLowerCase() === tagName)) { elems.push(node) } }) return elems } DOMElement.prototype.contains = function _Element_contains(element) { return domWalk(this, function (node) { return element === node }) || false }