dom-element.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. var domWalk = require("dom-walk")
  2. var dispatchEvent = require("./event/dispatch-event.js")
  3. var addEventListener = require("./event/add-event-listener.js")
  4. var removeEventListener = require("./event/remove-event-listener.js")
  5. var serializeNode = require("./serialize.js")
  6. var htmlns = "http://www.w3.org/1999/xhtml"
  7. module.exports = DOMElement
  8. function DOMElement(tagName, owner, namespace) {
  9. if (!(this instanceof DOMElement)) {
  10. return new DOMElement(tagName)
  11. }
  12. var ns = namespace === undefined ? htmlns : (namespace || null)
  13. this.tagName = ns === htmlns ? String(tagName).toUpperCase() : tagName
  14. this.nodeName = this.tagName
  15. this.className = ""
  16. this.dataset = {}
  17. this.childNodes = []
  18. this.parentNode = null
  19. this.style = {}
  20. this.ownerDocument = owner || null
  21. this.namespaceURI = ns
  22. this._attributes = {}
  23. if (this.tagName === 'INPUT') {
  24. this.type = 'text'
  25. }
  26. }
  27. DOMElement.prototype.type = "DOMElement"
  28. DOMElement.prototype.nodeType = 1
  29. DOMElement.prototype.appendChild = function _Element_appendChild(child) {
  30. if (child.parentNode) {
  31. child.parentNode.removeChild(child)
  32. }
  33. this.childNodes.push(child)
  34. child.parentNode = this
  35. return child
  36. }
  37. DOMElement.prototype.replaceChild =
  38. function _Element_replaceChild(elem, needle) {
  39. // TODO: Throw NotFoundError if needle.parentNode !== this
  40. if (elem.parentNode) {
  41. elem.parentNode.removeChild(elem)
  42. }
  43. var index = this.childNodes.indexOf(needle)
  44. needle.parentNode = null
  45. this.childNodes[index] = elem
  46. elem.parentNode = this
  47. return needle
  48. }
  49. DOMElement.prototype.removeChild = function _Element_removeChild(elem) {
  50. // TODO: Throw NotFoundError if elem.parentNode !== this
  51. var index = this.childNodes.indexOf(elem)
  52. this.childNodes.splice(index, 1)
  53. elem.parentNode = null
  54. return elem
  55. }
  56. DOMElement.prototype.insertBefore =
  57. function _Element_insertBefore(elem, needle) {
  58. // TODO: Throw NotFoundError if referenceElement is a dom node
  59. // and parentNode !== this
  60. if (elem.parentNode) {
  61. elem.parentNode.removeChild(elem)
  62. }
  63. var index = needle === null || needle === undefined ?
  64. -1 :
  65. this.childNodes.indexOf(needle)
  66. if (index > -1) {
  67. this.childNodes.splice(index, 0, elem)
  68. } else {
  69. this.childNodes.push(elem)
  70. }
  71. elem.parentNode = this
  72. return elem
  73. }
  74. DOMElement.prototype.setAttributeNS =
  75. function _Element_setAttributeNS(namespace, name, value) {
  76. var prefix = null
  77. var localName = name
  78. var colonPosition = name.indexOf(":")
  79. if (colonPosition > -1) {
  80. prefix = name.substr(0, colonPosition)
  81. localName = name.substr(colonPosition + 1)
  82. }
  83. if (this.tagName === 'INPUT' && name === 'type') {
  84. this.type = value;
  85. }
  86. else {
  87. var attributes = this._attributes[namespace] || (this._attributes[namespace] = {})
  88. attributes[localName] = {value: value, prefix: prefix}
  89. }
  90. }
  91. DOMElement.prototype.getAttributeNS =
  92. function _Element_getAttributeNS(namespace, name) {
  93. var attributes = this._attributes[namespace];
  94. var value = attributes && attributes[name] && attributes[name].value
  95. if (this.tagName === 'INPUT' && name === 'type') {
  96. return this.type;
  97. }
  98. if (typeof value !== "string") {
  99. return null
  100. }
  101. return value
  102. }
  103. DOMElement.prototype.removeAttributeNS =
  104. function _Element_removeAttributeNS(namespace, name) {
  105. var attributes = this._attributes[namespace];
  106. if (attributes) {
  107. delete attributes[name]
  108. }
  109. }
  110. DOMElement.prototype.hasAttributeNS =
  111. function _Element_hasAttributeNS(namespace, name) {
  112. var attributes = this._attributes[namespace]
  113. return !!attributes && name in attributes;
  114. }
  115. DOMElement.prototype.setAttribute = function _Element_setAttribute(name, value) {
  116. return this.setAttributeNS(null, name, value)
  117. }
  118. DOMElement.prototype.getAttribute = function _Element_getAttribute(name) {
  119. return this.getAttributeNS(null, name)
  120. }
  121. DOMElement.prototype.removeAttribute = function _Element_removeAttribute(name) {
  122. return this.removeAttributeNS(null, name)
  123. }
  124. DOMElement.prototype.hasAttribute = function _Element_hasAttribute(name) {
  125. return this.hasAttributeNS(null, name)
  126. }
  127. DOMElement.prototype.removeEventListener = removeEventListener
  128. DOMElement.prototype.addEventListener = addEventListener
  129. DOMElement.prototype.dispatchEvent = dispatchEvent
  130. // Un-implemented
  131. DOMElement.prototype.focus = function _Element_focus() {
  132. return void 0
  133. }
  134. DOMElement.prototype.toString = function _Element_toString() {
  135. return serializeNode(this)
  136. }
  137. DOMElement.prototype.getElementsByClassName = function _Element_getElementsByClassName(classNames) {
  138. var classes = classNames.split(" ");
  139. var elems = []
  140. domWalk(this, function (node) {
  141. if (node.nodeType === 1) {
  142. var nodeClassName = node.className || ""
  143. var nodeClasses = nodeClassName.split(" ")
  144. if (classes.every(function (item) {
  145. return nodeClasses.indexOf(item) !== -1
  146. })) {
  147. elems.push(node)
  148. }
  149. }
  150. })
  151. return elems
  152. }
  153. DOMElement.prototype.getElementsByTagName = function _Element_getElementsByTagName(tagName) {
  154. tagName = tagName.toLowerCase()
  155. var elems = []
  156. domWalk(this.childNodes, function (node) {
  157. if (node.nodeType === 1 && (tagName === '*' || node.tagName.toLowerCase() === tagName)) {
  158. elems.push(node)
  159. }
  160. })
  161. return elems
  162. }
  163. DOMElement.prototype.contains = function _Element_contains(element) {
  164. return domWalk(this, function (node) {
  165. return element === node
  166. }) || false
  167. }