--- /dev/null
+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
+}