diff --git a/js/js.libraries/src/core/domUtils.kt b/js/js.libraries/src/core/domUtils.kt deleted file mode 100644 index 931d7c8fd66..00000000000 --- a/js/js.libraries/src/core/domUtils.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.w3c.dom - -import java.util.AbstractList - -private class HTMLCollectionListView(val collection: HTMLCollection) : AbstractList() { - override val size: Int get() = collection.length - - override fun get(index: Int): HTMLElement = - when { - index in 0..size() - 1 -> collection.item(index) as HTMLElement - else -> throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size() - 1})") - } -} - -public fun HTMLCollection.asList(): List = HTMLCollectionListView(this) -public fun HTMLCollection?.toElementList(): List = this?.asList() ?: emptyList() - -private class DOMTokenListView(val delegate: DOMTokenList) : AbstractList() { - override val size: Int get() = delegate.length - - override fun get(index: Int) = - when { - index in 0..size() - 1 -> delegate.item(index)!! - else -> throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size() - 1})") - } -} - -public fun DOMTokenList.asList(): List = DOMTokenListView(this) \ No newline at end of file diff --git a/js/js.libraries/src/dom/Builder.kt b/js/js.libraries/src/dom/Builder.kt new file mode 100644 index 00000000000..4e6cd4aa3f3 --- /dev/null +++ b/js/js.libraries/src/dom/Builder.kt @@ -0,0 +1,41 @@ +package kotlin.dom.build + +import org.w3c.dom.* +import kotlin.dom.* + +/** + * Creates a new element which can be configured via a function + */ +fun Document.createElement(name: String, init: Element.() -> Unit): Element { + val elem = this.createElement(name)!! + elem.init() + return elem +} + +/** + * Creates a new element to an element which has an owner Document which can be configured via a function + */ +fun Element.createElement(name: String, doc: Document? = null, init: Element.() -> Unit): Element { + val elem = ownerDocument(doc).createElement(name)!! + elem.init() + return elem +} + +/** + * Adds a newly created element which can be configured via a function + */ +fun Document.addElement(name: String, init: Element.() -> Unit): Element { + val child = createElement(name, init) + this.appendChild(child) + return child +} + +/** + * Adds a newly created element to an element which has an owner Document which can be configured via a function + */ +fun Element.addElement(name: String, doc: Document? = null, init: Element.() -> Unit): Element { + val child = createElement(name, doc, init) + this.appendChild(child) + return child +} + diff --git a/js/js.libraries/src/dom/Classes.kt b/js/js.libraries/src/dom/Classes.kt new file mode 100644 index 00000000000..797f584381b --- /dev/null +++ b/js/js.libraries/src/dom/Classes.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.dom + +import org.w3c.dom.* + +/** Returns true if the element has the given CSS class style in its 'class' attribute */ +fun Element.hasClass(cssClass: String): Boolean = className.matches("""(^|.*\s+)$cssClass($|\s+.*)""".toRegex()) + +/** + * Adds CSS class to element. Has no effect if all specified classes are already in class attribute of the element + * + * @return true if at least one class has been added + */ +fun Element.addClass(vararg cssClasses: String): Boolean { + val missingClasses = cssClasses.filterNot { hasClass(it) } + if (missingClasses.isNotEmpty()) { + val presentClasses = className.trim() + className = buildString { + append(presentClasses) + if (!presentClasses.isEmpty()) { + append(" ") + } + missingClasses.joinTo(this, " ") + } + return true + } + + return false +} + +/** + * Removes all [cssClasses] from element. Has no effect if all specified classes are missing in class attribute of the element + * + * @return true if at least one class has been removed + */ +fun Element.removeClass(vararg cssClasses: String): Boolean { + if (cssClasses.any { hasClass(it) }) { + val toBeRemoved = cssClasses.toSet() + className = className.trim().split("\\s+".toRegex()).filter { it !in toBeRemoved }.joinToString(" ") + return true + } + + return false +} diff --git a/js/js.libraries/src/dom/Dom.kt b/js/js.libraries/src/dom/Dom.kt new file mode 100644 index 00000000000..1684006b228 --- /dev/null +++ b/js/js.libraries/src/dom/Dom.kt @@ -0,0 +1,182 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.dom + +import org.w3c.dom.* +import java.util.* +import kotlin.dom.* +import kotlin.support.* + +// Properties + +/** Returns the children of the element as a list */ +fun Element?.children(): List { + return this?.childNodes?.asList() ?: emptyList() +} + +/** Returns the child elements of this element */ +fun Element?.childElements(): List = this?.childNodes?.filterElements() ?: emptyList() + +/** Returns the child elements of this element with the given name */ +fun Element?.childElements(name: String): List = this?.childNodes?.filterElements()?.filter { it.nodeName == name } ?: emptyList() + +/** The descendant elements of this document */ +@Deprecated("Use elements() function instead", ReplaceWith("this.elements()")) +val Document?.elements: List + get() = this.elements() + +/** The descendant elements of this elements */ +@Deprecated("Use elements() function instead", ReplaceWith("this?.elements() ?: emptyList()")) +val Element?.elements: List + get() = this?.elements() ?: emptyList() + +@Deprecated("Use non-nullable receiver version elements()", ReplaceWith("this?.elements(localName) ?: emptyList()")) +fun Element?.elements(localName: String): List = this?.elements(localName) ?: emptyList() + +/** Returns all the descendant elements given the local element name */ +fun Element.elements(localName: String = "*"): List { + return this.getElementsByTagName(localName).asElementList() +} + +/** Returns all the descendant elements given the local element name */ +fun Document?.elements(localName: String = "*"): List { + return this?.getElementsByTagName(localName)?.asElementList() ?: emptyList() +} + +@Deprecated("Use non-nullable elements function instead", ReplaceWith("this?.elements(namespaceUri, localName) ?: emptyList()")) +fun Element?.elements(namespaceUri: String, localName: String): List = this?.elements(namespaceUri, localName) ?: emptyList() + +/** Returns all the descendant elements given the namespace URI and local element name */ +fun Element.elements(namespaceUri: String, localName: String): List { + return this.getElementsByTagNameNS(namespaceUri, localName).asElementList() +} + +/** Returns all the descendant elements given the namespace URI and local element name */ +fun Document?.elements(namespaceUri: String, localName: String): List { + return this?.getElementsByTagNameNS(namespaceUri, localName)?.asElementList() ?: emptyList() +} + +@Deprecated("Use non-null function instead with elvis", ReplaceWith("this?.asList() ?: emptyList()")) +fun NodeList?.asList(): List = this?.asList() ?: emptyList() + +fun NodeList.asList() : List = NodeListAsList(this) + +@Deprecated("Use asElementList() instead", ReplaceWith("this?.asElementList() ?: emptyList()")) +fun NodeList?.toElementList(): List = this?.asElementList() ?: emptyList() + +/** + * Returns view with assumption that it contains only elements. Will crash in runtime if there are non-element nodes in + * the list during access such items. So [filterElements] would be better solution. + */ +fun NodeList.asElementList(): List = if (length == 0) emptyList() else ElementListAsList(this) + +@Suppress("UNCHECKED_CAST") +fun List.filterElements(): List = filter { it.isElement } as List +fun NodeList.filterElements(): List = asList().filterElements() + +private class NodeListAsList(private val delegate: NodeList) : AbstractList() { + override val size: Int get() = delegate.length + + override fun get(index: Int): Node = when { + index in 0..size - 1 -> delegate.item(index)!! + else -> throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size - 1})") + } +} + +private class ElementListAsList(private val nodeList: NodeList) : AbstractList() { + override fun get(index: Int): Element { + val node = nodeList.item(index) + if (node == null) { + throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index) + } else if (node.nodeType == Node.ELEMENT_NODE) { + return node as Element + } else { + throw IllegalArgumentException("Node is not an Element as expected but is $node") + } + } + + override val size: Int get() = nodeList.length +} + +/** Returns an [Iterator] over the next siblings of this node */ +fun Node.nextSiblings(): Iterable = NextSiblings(this) + +private class NextSiblings(private var node: Node) : Iterable { + override fun iterator(): Iterator = object : AbstractIterator() { + override fun computeNext(): Unit { + val nextValue = node.nextSibling + if (nextValue != null) { + setNext(nextValue) + node = nextValue + } else { + done() + } + } + } +} + +/** Returns an [Iterator] over the next siblings of this node */ +fun Node.previousSiblings(): Iterable = PreviousSiblings(this) + +private class PreviousSiblings(private var node: Node) : Iterable { + override fun iterator(): Iterator = object : AbstractIterator() { + override fun computeNext(): Unit { + val nextValue = node.previousSibling + if (nextValue != null) { + setNext(nextValue) + node = nextValue + } else { + done() + } + } + } +} + +/** + * it is *true* when [Node.nodeType] is TEXT_NODE or CDATA_SECTION_NODE + */ +val Node.isText : Boolean + get() = nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE + + +/** + * `true` if it's an element node + */ +val Node.isElement: Boolean + get() = nodeType == Node.ELEMENT_NODE + +/** Returns the attribute value or empty string if its not present */ +@Deprecated("Use getAttribute with elvis operator", ReplaceWith("this.getAttribute(name) ?: \"\"")) +fun Element.attribute(name: String): String { + return this.getAttribute(name) ?: "" +} + +@Deprecated("Use asList().firstOrNull() instead", ReplaceWith("this?.asList()?.firstOrNull()")) +val NodeList?.head: Node? + get() = this?.asList()?.firstOrNull() + +@Deprecated("Use asList().firstOrNull() instead", ReplaceWith("this?.asList()?.firstOrNull()")) +val NodeList?.first: Node? + get() = this?.asList()?.firstOrNull() + +@Deprecated("Use asList().lastOrNull() instead", ReplaceWith("this?.asList()?.lastOrNull()")) +val NodeList?.last: Node? + get() = this?.asList()?.lastOrNull() + +@Deprecated("Use asList().lastOrNull() instead instead", ReplaceWith("last")) +val NodeList?.tail: Node? + get() = this?.asList()?.lastOrNull() diff --git a/libraries/stdlib/src/kotlin/dom/DomEvents.kt b/js/js.libraries/src/dom/DomEvents.kt similarity index 91% rename from libraries/stdlib/src/kotlin/dom/DomEvents.kt rename to js/js.libraries/src/dom/DomEvents.kt index 2649931731c..50303099dfc 100644 --- a/libraries/stdlib/src/kotlin/dom/DomEvents.kt +++ b/js/js.libraries/src/dom/DomEvents.kt @@ -1,5 +1,3 @@ -@file:kotlin.jvm.JvmMultifileClass -@file:kotlin.jvm.JvmName("DomEventsKt") package kotlin.dom import java.io.Closeable @@ -31,7 +29,7 @@ public fun mouseEventHandler(handler: (MouseEvent) -> Unit): EventListener { /** * Registers a handler on the named event */ -public fun Node?.on(name: String, capture: Boolean, handler: (Event) -> Unit): Closeable? { +public fun Node.on(name: String, capture: Boolean, handler: (Event) -> Unit): Closeable? { return on(name, capture, eventHandler(handler)) } diff --git a/js/js.libraries/src/dom/DomJS.kt b/js/js.libraries/src/dom/DomJS.kt new file mode 100644 index 00000000000..5b1e7c9ca9d --- /dev/null +++ b/js/js.libraries/src/dom/DomJS.kt @@ -0,0 +1,42 @@ +package kotlin.dom + +import org.w3c.dom.* +import org.w3c.dom.DOMTokenList +import org.w3c.dom.HTMLCollection +import org.w3c.dom.HTMLElement +import java.util.* + +/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ +operator fun Document?.get(selector: String): List { + return this?.querySelectorAll(selector)?.asList()?.filterElements() ?: emptyList() +} + +/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ +operator fun Element.get(selector: String): List { + return querySelectorAll(selector).asList().filterElements() +} + +private class HTMLCollectionListView(val collection: HTMLCollection) : AbstractList() { + override val size: Int get() = collection.length + + override fun get(index: Int): HTMLElement = + when { + index in 0..size - 1 -> collection.item(index) as HTMLElement + else -> throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size - 1})") + } +} + +public fun HTMLCollection.asList(): List = HTMLCollectionListView(this) + +private class DOMTokenListView(val delegate: DOMTokenList) : AbstractList() { + override val size: Int get() = delegate.length + + override fun get(index: Int) = + when { + index in 0..size - 1 -> delegate.item(index)!! + else -> throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size - 1})") + } +} + +public fun DOMTokenList.asList(): List = DOMTokenListView(this) +internal fun HTMLCollection.asElementList(): List = asList() diff --git a/js/js.libraries/src/dom/Mutations.kt b/js/js.libraries/src/dom/Mutations.kt new file mode 100644 index 00000000000..9e5737a7dc2 --- /dev/null +++ b/js/js.libraries/src/dom/Mutations.kt @@ -0,0 +1,61 @@ +package kotlin.dom + +import org.w3c.dom.* + +/** Removes all the children from this node */ +fun Node.clear() { + while (hasChildNodes()) { + removeChild(firstChild!!) + } +} + +/** + * Removes this node from parent node. Does nothing if no parent node + */ +fun Node.removeFromParent() { + parentNode?.removeChild(this) +} + +operator fun Node.plus(child: Node): Node { + appendChild(child) + return this +} + +operator fun Element.plus(text: String): Element = appendText(text) +operator fun Element.plusAssign(text: String): Unit { + appendText(text) +} + +/** Returns the owner document of the element or uses the provided document */ +fun Node.ownerDocument(doc: Document? = null): Document = when { + nodeType == Node.DOCUMENT_NODE -> this as Document + else -> doc ?: ownerDocument ?: throw IllegalArgumentException("Neither node contains nor parameter doc provides an owner document for $this") +} + +/** + * Adds a newly created text node to an element which either already has an owner Document or one must be provided as a parameter + */ +@Deprecated("Use appendText() instead", ReplaceWith("appendText(text, doc)")) +fun Element.addText(text: String, doc: Document? = null): Element = appendText(text, doc) + +/** + * Adds a newly created text node to an element which either already has an owner Document or one must be provided as a parameter + */ +@Deprecated("Use appendText() instead", ReplaceWith("appendText(text)")) +fun Element.addText(text: String): Element = appendText(text) + + +/** + * Creates text node and append it to the element + */ +fun Element.appendText(text: String, doc : Document? = null): Element { + appendChild(ownerDocument(doc).createTextNode(text)) + return this +} + +/** + * Appends the node to the specified parent element + */ +fun Node.appendTo(parent: Element) { + parent.appendChild(this) +} diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/StdLibTestToJSTest.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/StdLibTestToJSTest.java index a0c13ab0d62..ff83fb8d3a7 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/StdLibTestToJSTest.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/StdLibTestToJSTest.java @@ -35,8 +35,6 @@ public class StdLibTestToJSTest extends StdLibQUnitTestSupport { "../../../js/js.libraries/test/core/assertTypeEquals.kt", "text/StringTest.kt", // TODO review: somethings FAILED if run: - "js/JsDomTest.kt", - "dom/DomTest.kt", "collections/SequenceTest.kt", "collections/IterableTests.kt", "collections/ArraysTest.kt", diff --git a/js/js.translator/testData/stdlib/cases/browserDocumentAccess.kt b/js/js.translator/testData/stdlib/cases/browserDocumentAccess.kt index 9f4c6967a28..084a92cb791 100644 --- a/js/js.translator/testData/stdlib/cases/browserDocumentAccess.kt +++ b/js/js.translator/testData/stdlib/cases/browserDocumentAccess.kt @@ -1,6 +1,6 @@ package test.browser -import kotlin.js.dom.html.document +import kotlin.browser.document import org.w3c.dom.Node fun box(): String { diff --git a/libraries/stdlib/src/kotlin/dom/Dom.kt b/libraries/stdlib/src/kotlin/dom/Dom.kt deleted file mode 100644 index d7facaa6d93..00000000000 --- a/libraries/stdlib/src/kotlin/dom/Dom.kt +++ /dev/null @@ -1,405 +0,0 @@ -@file:kotlin.jvm.JvmMultifileClass -@file:kotlin.jvm.JvmName("DomKt") -package kotlin.dom - -import kotlin.support.* -import java.util.* -import org.w3c.dom.* - -// TODO should not need this - its here for the JS stuff -import java.lang.IllegalArgumentException -import java.lang.IndexOutOfBoundsException - -// Properties - -@Deprecated("use textContent directly instead") -public var Node.text: String - get() = textContent ?: "" - set(value) { - textContent = value - } - -@Deprecated("You shouldn't use it as setter will drop all elements and get may return not exactly content user can expect") -public var Element.childrenText: String - get() { - val buffer = StringBuilder() - val nodeList = this.childNodes - var i = 0 - val size = nodeList.length - while (i < size) { - val node = nodeList.item(i) - if (node != null) { - if (node.isText) { - buffer.append(node.nodeValue) - } - } - i++ - } - return buffer.toString() - } - set(value) { - val element = this - // lets remove all the previous text nodes first - for (node in element.children()) { - if (node.isText) { - removeChild(node) - } - } - element.addText(value) - } - -public var Element.classes: String - get() = this.getAttribute("class") ?: "" - set(value) { - this.setAttribute("class", value) - } - -/** Returns true if the element has the given CSS class style in its 'class' attribute */ -public fun Element.hasClass(cssClass: String): Boolean = classes.matches("""(^|.*\s+)$cssClass($|\s+.*)""".toRegex()) - - -/** Returns the children of the element as a list */ -public fun Element?.children(): List { - return this?.childNodes.toList() -} - -/** Returns the child elements of this element */ -public fun Element?.childElements(): List { - return children().filter{ it.nodeType == Node.ELEMENT_NODE }.map { it as Element } -} - -/** Returns the child elements of this element with the given name */ -public fun Element?.childElements(name: String): List { - return children().filter{ it.nodeType == Node.ELEMENT_NODE && it.nodeName == name }.map { it as Element } -} - -/** The descendant elements of this document */ -public val Document?.elements: List - get() = this?.getElementsByTagName("*").toElementList() - -/** The descendant elements of this elements */ -public val Element?.elements: List - get() = this?.getElementsByTagName("*").toElementList() - - -/** Returns all the descendant elements given the local element name */ -public fun Element?.elements(localName: String): List { - return this?.getElementsByTagName(localName).toElementList() -} - -/** Returns all the descendant elements given the local element name */ -public fun Document?.elements(localName: String): List { - return this?.getElementsByTagName(localName).toElementList() -} - -/** Returns all the descendant elements given the namespace URI and local element name */ -public fun Element?.elements(namespaceUri: String, localName: String): List { - return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList() -} - -/** Returns all the descendant elements given the namespace URI and local element name */ -public fun Document?.elements(namespaceUri: String, localName: String): List { - return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList() -} - -public fun NodeList?.asList() : List = if (this == null) emptyList() else NodeListAsList(this) -@Deprecated("use asList instead", ReplaceWith("asList()")) -public fun NodeList?.toList(): List = asList() - -public fun NodeList?.toElementList(): List { - return if (this == null) { - // TODO the following is easier to convert to JS - //emptyElementList() - ArrayList() - } - else { - ElementListAsList(this) - } -} - -/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ -public operator fun Document?.get(selector: String): List { - val root = this?.documentElement - return if (root != null) { - if (selector == "*") { - elements - } else if (selector.startsWith(".")) { - elements.filter{ it.hasClass(selector.substring(1)) }.toList() - } else if (selector.startsWith("#")) { - val id = selector.substring(1) - val element = this?.getElementById(id) - return if (element != null) - arrayListOf(element) - else - emptyList() - } else { - // assume its a vanilla element name - elements(selector) - } - } else { - emptyList() - } -} - -/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ -public operator fun Element.get(selector: String): List { - return if (selector == "*") { - elements - } else if (selector.startsWith(".")) { - elements.filter{ it.hasClass(selector.substring(1)) }.toList() - } else if (selector.startsWith("#")) { - val element = this.ownerDocument?.getElementById(selector.substring(1)) - return if (element != null) - arrayListOf(element) - else - emptyList() - } else { - // assume its a vanilla element name - elements(selector) - } -} - - -// Helper methods - - -/** - * Adds CSS class to element. Has no effect if all specified classes are already in class attribute of the element - */ -public fun Element.addClass(vararg cssClasses: String): Boolean { - val missingClasses = cssClasses.filterNot { hasClass(it) } - if (missingClasses.isNotEmpty()) { - val presentClasses = classes.trim() - classes = buildString { - append(presentClasses) - if (!presentClasses.isEmpty()) { - append(" ") - } - missingClasses.joinTo(this, " ") - } - return true - } - - return false -} - -/** - * Removes all [cssClasses] from element. Has no effect if all specified classes are missing in class attribute of the element - */ -public fun Element.removeClass(vararg cssClasses: String): Boolean { - if (cssClasses.any { hasClass(it) }) { - val toBeRemoved = cssClasses.toSet() - classes = classes.trim().split("\\s+".toRegex()).filter { it !in toBeRemoved }.joinToString(" ") - return true - } - - return false -} - -/** Removes all the children from this node */ -public fun Node.clear() { - while (hasChildNodes()) { - removeChild(firstChild!!) - } -} - -/** - * Removes this node from parent node. Does nothing if no parent node - */ -public fun Node.removeFromParent() { - parentNode?.removeChild(this) -} - -private class NodeListAsList(private val delegate: NodeList) : AbstractList() { - override val size: Int get() = delegate.length - - override fun get(index: Int): Node = when { - index in 0..size() - 1 -> delegate.item(index)!! - else -> throw IndexOutOfBoundsException("index $index is not in range [0 .. ${size() - 1})") - } -} - -private class ElementListAsList(private val nodeList: NodeList) : AbstractList() { - override fun get(index: Int): Element { - val node = nodeList.item(index) - if (node == null) { - throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index) - } else if (node.nodeType == Node.ELEMENT_NODE) { - return node as Element - } else { - throw IllegalArgumentException("Node is not an Element as expected but is $node") - } - } - - override val size: Int get() = nodeList.length -} - -/** Returns an [Iterator] over the next siblings of this node */ -public fun Node.nextSiblings(): Iterable = NextSiblings(this) - -private class NextSiblings(private var node: Node) : Iterable { - override fun iterator(): Iterator = object : AbstractIterator() { - override fun computeNext(): Unit { - val nextValue = node.nextSibling - if (nextValue != null) { - setNext(nextValue) - node = nextValue - } else { - done() - } - } - } -} - -/** Returns an [Iterator] over the next siblings of this node */ -public fun Node.previousSiblings(): Iterable = PreviousSiblings(this) - -private class PreviousSiblings(private var node: Node) : Iterable { - override fun iterator(): Iterator = object : AbstractIterator() { - override fun computeNext(): Unit { - val nextValue = node.previousSibling - if (nextValue != null) { - setNext(nextValue) - node = nextValue - } else { - done() - } - } - } -} - -/** - * it is *true* when [Node.nodeType] is TEXT_NODE or CDATA_SECTION_NODE - */ -public val Node.isText : Boolean - get() = nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE - - -/** Returns the attribute value or empty string if its not present */ -public fun Element.attribute(name: String): String { - return this.getAttribute(name) ?: "" -} - -public val NodeList?.head: Node? - get() = if (this != null && this.length > 0) this.item(0) else null - -public val NodeList?.first: Node? - get() = this.head - -public val NodeList?.tail: Node? - get() { - if (this == null) { - return null - } - else { - val s = this.length - return if (s > 0) this.item(s - 1) else null - } - } - -public val NodeList?.last: Node? - get() = this.tail - - -/** Converts the node list to an XML String */ -public fun NodeList?.toXmlString(xmlDeclaration: Boolean = false): String { - return if (this == null) - "" else { - nodesToXmlString(this.toList(), xmlDeclaration) - } -} - -/** Converts the collection of nodes to an XML String */ -public fun nodesToXmlString(nodes: Iterable, xmlDeclaration: Boolean = false): String { - return nodes.map { it.toXmlString(xmlDeclaration) }.joinToString() -} - -// Syntax sugar - -public operator fun Node.plus(child: Node?): Node { - if (child != null) { - this.appendChild(child) - } - return this -} - -public operator fun Element.plus(text: String?): Element = this.addText(text) - -public operator fun Element.plusAssign(text: String?): Element = this.addText(text) - - -// Builder - -/** - * Creates a new element which can be configured via a function - */ -public fun Document.createElement(name: String, init: Element.() -> Unit): Element { - val elem = this.createElement(name)!! - elem.init() - return elem -} - -/** - * Creates a new element to an element which has an owner Document which can be configured via a function - */ -public fun Element.createElement(name: String, doc: Document? = null, init: Element.() -> Unit): Element { - val elem = ownerDocument(doc).createElement(name)!! - elem.init() - return elem -} - -/** Returns the owner document of the element or uses the provided document */ -public fun Node.ownerDocument(doc: Document? = null): Document { - val answer = if (this.nodeType == Node.DOCUMENT_NODE) this as Document - else if (doc == null) this.ownerDocument - else doc - - if (answer == null) { - throw IllegalArgumentException("Element does not have an ownerDocument and none was provided for: ${this}") - } else { - return answer - } -} - -/** -Adds a newly created element which can be configured via a function -*/ -public fun Document.addElement(name: String, init: Element.() -> Unit): Element { - val child = createElement(name, init) - this.appendChild(child) - return child -} - -/** -Adds a newly created element to an element which has an owner Document which can be configured via a function -*/ -public fun Element.addElement(name: String, doc: Document? = null, init: Element.() -> Unit): Element { - val child = createElement(name, doc, init) - this.appendChild(child) - return child -} - -/** -Adds a newly created text node to an element which either already has an owner Document or one must be provided as a parameter -*/ -public fun Element.addText(text: String?, doc: Document? = null): Element { - if (text != null) { - val child = this.ownerDocument(doc).createTextNode(text)!! - this.appendChild(child) - } - return this -} - -/** - * Creates text node and append it to the element - */ -public fun Element.appendText(text: String, doc : Document = this.ownerDocument!!) { - appendChild(doc.createTextNode(text)) -} - -/** - * Appends the node to the specified parent element - */ -public fun Node.appendTo(parent: Element) { - parent.appendChild(this) -} diff --git a/libraries/stdlib/src/kotlin/dom/DomEventsJVM.kt b/libraries/stdlib/src/kotlin/dom/DomEventsJVM.kt deleted file mode 100644 index 58a7754b756..00000000000 --- a/libraries/stdlib/src/kotlin/dom/DomEventsJVM.kt +++ /dev/null @@ -1,76 +0,0 @@ -@file:kotlin.jvm.JvmMultifileClass -@file:kotlin.jvm.JvmName("DomEventsKt") -package kotlin.dom - -import org.w3c.dom.events.Event -import org.w3c.dom.events.EventTarget -import org.w3c.dom.events.MouseEvent - -// JavaScript style properties for JVM : TODO could auto-generate these -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("bubbles"), level = DeprecationLevel.HIDDEN) -public val Event.bubbles: Boolean - get() = getBubbles() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("cancelable"), level = DeprecationLevel.HIDDEN) -public val Event.cancelable: Boolean - get() = getCancelable() - -public val Event.getCurrentTarget: EventTarget? - get() = getCurrentTarget() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("eventPhase"), level = DeprecationLevel.HIDDEN) -public val Event.eventPhase: Short - get() = getEventPhase() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("target"), level = DeprecationLevel.HIDDEN) -public val Event.target: EventTarget? - get() = getTarget() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("timeStamp"), level = DeprecationLevel.HIDDEN) -public val Event.timeStamp: Long - get() = getTimeStamp() - -// TODO we can't use 'type' as the property name in Kotlin so we should fix it in JS -public val Event.eventType: String - get() = getType()!! - - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("altKey"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.altKey: Boolean - get() = getAltKey() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("button"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.button: Short - get() = getButton() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("clientX"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.clientX: Int - get() = getClientX() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("clientY"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.clientY: Int - get() = getClientY() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("ctrlKey"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.ctrlKey: Boolean - get() = getCtrlKey() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("metaKey"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.metaKey: Boolean - get() = getMetaKey() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("relatedTarget"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.relatedTarget: EventTarget? - get() = getRelatedTarget() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("screenX"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.screenX: Int - get() = getScreenX() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("screenY"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.screenY: Int - get() = getScreenY() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("shiftKey"), level = DeprecationLevel.HIDDEN) -public val MouseEvent.shiftKey: Boolean - get() = getShiftKey() diff --git a/libraries/stdlib/src/kotlin/dom/DomJVM.kt b/libraries/stdlib/src/kotlin/dom/DomJVM.kt deleted file mode 100644 index 45a5edbaa55..00000000000 --- a/libraries/stdlib/src/kotlin/dom/DomJVM.kt +++ /dev/null @@ -1,253 +0,0 @@ - -/** - * JVM specific API implementations using JAXP and so forth which would not be used when compiling to JS - */ -@file:kotlin.jvm.JvmMultifileClass -@file:kotlin.jvm.JvmName("DomKt") -package kotlin.dom - -import org.w3c.dom.* -import org.xml.sax.InputSource -import java.io.File -import java.io.InputStream -import java.io.StringWriter -import java.io.Writer -import java.util.* -import javax.xml.parsers.DocumentBuilder -import javax.xml.parsers.DocumentBuilderFactory -import javax.xml.transform.OutputKeys -import javax.xml.transform.Source -import javax.xml.transform.Transformer -import javax.xml.transform.TransformerFactory -import javax.xml.transform.dom.DOMSource -import javax.xml.transform.stream.StreamResult - -// JavaScript style properties - TODO could auto-generate these -@Deprecated("Use getNodeName()", ReplaceWith("getNodeName() ?: \"\"")) -public val Node.nodeName: String - get() = getNodeName() ?: "" - -@Deprecated("Use getNodeValue()", ReplaceWith("getNodeValue() ?: \"\"")) -public val Node.nodeValue: String - get() = getNodeValue() ?: "" - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("nodeType"), level = DeprecationLevel.HIDDEN) -public val Node.nodeType: Short - get() = getNodeType() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("parentNode"), level = DeprecationLevel.HIDDEN) -public val Node.parentNode: Node? - get() = getParentNode() - -@Deprecated("Use getChildNodes()", ReplaceWith("getChildNodes()!!")) -public val Node.childNodes: NodeList - get() = getChildNodes()!! - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("firstChild"), level = DeprecationLevel.HIDDEN) -public val Node.firstChild: Node? - get() = getFirstChild() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("lastChild"), level = DeprecationLevel.HIDDEN) -public val Node.lastChild: Node? - get() = getLastChild() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("nextSibling"), level = DeprecationLevel.HIDDEN) -public val Node.nextSibling: Node? - get() = getNextSibling() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("previousSibling"), level = DeprecationLevel.HIDDEN) -public val Node.previousSibling: Node? - get() = getPreviousSibling() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("attributes"), level = DeprecationLevel.HIDDEN) -public val Node.attributes: NamedNodeMap? - get() = getAttributes() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("ownerDocument"), level = DeprecationLevel.HIDDEN) -public val Node.ownerDocument: Document? - get() = getOwnerDocument() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("documentElement"), level = DeprecationLevel.HIDDEN) -public val Document.documentElement: Element? - get() = this.getDocumentElement() - -@Deprecated("Use getNamespaceURI()", ReplaceWith("getNamespaceURI() ?: \"\"")) -public val Node.namespaceURI: String - get() = getNamespaceURI() ?: "" - -@Deprecated("Use getPrefix()", ReplaceWith("getPrefix() ?: \"\"")) -public val Node.prefix: String - get() = getPrefix() ?: "" - -@Deprecated("Use getLocalName()", ReplaceWith("getLocalName() ?: \"\"")) -public val Node.localName: String - get() = getLocalName() ?: "" - -@Deprecated("Use getBaseURI", ReplaceWith("getBaseURI() ?: \"\"")) -public val Node.baseURI: String - get() = getBaseURI() ?: "" - -@Deprecated("Use getTextContent()/setTextContent()") -public var Node.textContent: String - get() = getTextContent() ?: "" - set(value) { - setTextContent(value) - } - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("length"), level = DeprecationLevel.HIDDEN) -public val DOMStringList.length: Int - get() = this.getLength() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("length"), level = DeprecationLevel.HIDDEN) -public val NameList.length: Int - get() = this.getLength() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("length"), level = DeprecationLevel.HIDDEN) -public val DOMImplementationList.length: Int - get() = this.getLength() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("length"), level = DeprecationLevel.HIDDEN) -public val NodeList.length: Int - get() = this.getLength() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("length"), level = DeprecationLevel.HIDDEN) -public val CharacterData.length: Int - get() = this.getLength() - -@Deprecated("Is replaced with automatic synthetic extension", ReplaceWith("length"), level = DeprecationLevel.HIDDEN) -public val NamedNodeMap.length: Int - get() = this.getLength() - -public var Element.id: String - get() = this.getAttribute("id") ?: "" - set(value) { - this.setAttribute("id", value) - this.setIdAttribute("id", true) - } - -public var Element.style: String - get() = this.getAttribute("style") ?: "" - set(value) { - this.setAttribute("style", value) - } - -/** - * Returns the HTML representation of the node - */ -public val Node.outerHTML: String - get() = toXmlString() - -/** - * Returns the HTML representation of the node - */ -public val Node.innerHTML: String - get() = childNodes.outerHTML - -/** - * Returns the HTML representation of the nodes - */ -public val NodeList.outerHTML: String - get() = toList().map { it.innerHTML }.joinToString("") - -/** Returns an [Iterator] of all the next [Element] siblings */ -public fun Node.nextElements(): List = nextSiblings().filterIsInstance() - -/** Returns an [Iterator] of all the previous [Element] siblings */ -public fun Node.previousElements(): List = previousSiblings().filterIsInstance() - - -public var Element.classSet: MutableSet - get() { - val answer = LinkedHashSet() - val array = this.classes.split("""\s""".toPattern()) - for (s in array) { - if (s.length() > 0) { - answer.add(s) - } - } - return answer - } - set(value) { - this.classes = value.joinToString(" ") - } - - -/** Creates a new document with the given document builder*/ -public fun createDocument(builder: DocumentBuilder): Document { - return builder.newDocument() -} - -/** Creates a new document with an optional DocumentBuilderFactory */ -public fun createDocument(builderFactory: DocumentBuilderFactory = defaultDocumentBuilderFactory()): Document { - return createDocument(builderFactory.newDocumentBuilder()) -} - -/** - * Returns the default [DocumentBuilderFactory] - */ -public fun defaultDocumentBuilderFactory(): DocumentBuilderFactory { - return DocumentBuilderFactory.newInstance()!! -} - -/** - * Returns the default [DocumentBuilder] - */ -public fun defaultDocumentBuilder(builderFactory: DocumentBuilderFactory = defaultDocumentBuilderFactory()): DocumentBuilder { - return builderFactory.newDocumentBuilder() -} - -/** - * Parses the XML document using the given *file* - */ -public fun parseXml(file: File, builder: DocumentBuilder = defaultDocumentBuilder()): Document { - return builder.parse(file)!! -} - -/** - * Parses the XML document using the given *uri* - */ -public fun parseXml(uri: String, builder: DocumentBuilder = defaultDocumentBuilder()): Document { - return builder.parse(uri)!! -} - -/** - * Parses the XML document using the given *inputStream* - */ -public fun parseXml(inputStream: InputStream, builder: DocumentBuilder = defaultDocumentBuilder()): Document { - return builder.parse(inputStream)!! -} - -/** - * Parses the XML document using the given *inputSource* - */ -public fun parseXml(inputSource: InputSource, builder: DocumentBuilder = defaultDocumentBuilder()): Document { - return builder.parse(inputSource)!! -} - - -/** Creates a new TrAX transformer */ -public fun createTransformer(source: Source? = null, factory: TransformerFactory = TransformerFactory.newInstance()!!): Transformer { - val transformer = if (source != null) { - factory.newTransformer(source) - } else { - factory.newTransformer() - } - return transformer!! -} - -/** Converts the node to an XML String */ -public fun Node.toXmlString(): String = toXmlString(false) - -/** Converts the node to an XML String */ -public fun Node.toXmlString(xmlDeclaration: Boolean): String { - val writer = StringWriter() - writeXmlString(writer, xmlDeclaration) - return writer.toString() -} - -/** Converts the node to an XML String and writes it to the given [Writer] */ -public fun Node.writeXmlString(writer: Writer, xmlDeclaration: Boolean): Unit { - val transformer = createTransformer() - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, if (xmlDeclaration) "no" else "yes") - transformer.transform(DOMSource(this), StreamResult(writer)) -} diff --git a/libraries/stdlib/test/browser/BrowserTest.kt b/libraries/stdlib/test/browser/BrowserTest.kt deleted file mode 100644 index 9869e581e66..00000000000 --- a/libraries/stdlib/test/browser/BrowserTest.kt +++ /dev/null @@ -1,33 +0,0 @@ -package test.browser - -import kotlin.dom.* -import kotlin.browser.* - -import kotlin.test.* -import org.junit.Test as test - -class BrowserTest { - - @test fun accessBrowserDOM() { - registerBrowserPage() - - val h1 = document["h1"].first() - assertEquals("Hello World!", h1.textContent) - } - - protected fun registerBrowserPage() { - // lets simulate being a browser registering its DOM - val doc = createDocument() - doc.addElement("html") { - addElement("body") { - addElement("h1") { - addText("Hello World!") - } - addElement("p") { - addText("This is some text content") - } - } - } - document = doc - } -} \ No newline at end of file diff --git a/libraries/stdlib/test/dom/DomBuilderTest.kt b/libraries/stdlib/test/dom/DomBuilderTest.kt deleted file mode 100644 index 6085ba1a3c3..00000000000 --- a/libraries/stdlib/test/dom/DomBuilderTest.kt +++ /dev/null @@ -1,130 +0,0 @@ -package test.dom - -import kotlin.dom.* -import kotlin.test.* -import org.w3c.dom.* -import org.junit.Test as test - -class DomBuilderTest() { - - @test fun buildDocument() { - var doc = createDocument() - - assertTrue { - doc["grandchild"].isEmpty() - } - - doc.addElement("foo") { - id = "id1" - style = "bold" - classes = "bar" - addElement("child") { - id = "id2" - classes = "another" - addElement("grandChild") { - id = "id3" - classes = " bar tiny" - addText("Hello World!") - // TODO support neater syntax sugar for adding text? - // += "Hello World!" - } - addElement("grandChild2") { - id = "id3" - classes = "tiny thing bar " - addText("Hello World!") - // TODO support neater syntax sugar for adding text? - // += "Hello World!" - } - } - } - - // test css selections on document - assertEquals(0, doc[".doesNotExist"].size()) - assertEquals(1, doc[".another"].size()) - assertEquals(3, doc[".bar"].size()) - assertEquals(2, doc[".tiny"].size()) - - // element tag selections - assertEquals(0, doc["doesNotExist"].size()) - assertEquals(1, doc["foo"].size()) - assertEquals(1, doc["child"].size()) - assertEquals(1, doc["grandChild"].size()) - - // id selections - assertEquals(1, doc["#id1"].size()) - assertEquals(1, doc["#id2"].size()) - assertEquals(1, doc["#id3"].size()) - - val root = doc.documentElement - if (root == null) { - fail("No root!") - } else { - assertTrue { - root.hasClass("bar") - } - - // test css selections on element - assertEquals(0, root[".doesNotExist"].size()) - assertEquals(1, root[".another"].size()) - assertEquals(2, root[".bar"].size()) - assertEquals(2, root[".tiny"].size()) - - // element tag selections - assertEquals(0, root["doesNotExist"].size()) - assertEquals(0, root["foo"].size()) - assertEquals(1, root["child"].size()) - assertEquals(1, root["grandChild"].size()) - - // id selections - assertEquals(1, root["#id1"].size()) - assertEquals(1, root["#id2"].size()) - assertEquals(1, root["#id3"].size()) - - // iterating through next element siblings - for (e in root.nextElements()) { - println("found element: $e") - } - - } - val grandChild = doc["grandChild"].firstOrNull() - if (grandChild != null) { - assertEquals("Hello World!", grandChild.textContent) - assertEquals(" bar tiny", grandChild.attribute("class")) - - // test the classSet - val classSet = grandChild.classSet - - assertTrue(classSet.contains("bar")) - assertTrue(classSet.contains("tiny")) - assertTrue(classSet.size() == 2 ) - assertFalse(classSet.contains("doesNotExist")) - - // lets add a new class and some existing classes - grandChild.addClass("bar") - grandChild.addClass("newThingy") - assertEquals("bar tiny newThingy", grandChild.classes) - - // remove - grandChild.removeClass("bar") - assertEquals("tiny newThingy", grandChild.classes) - - grandChild.removeClass("tiny") - assertEquals("newThingy", grandChild.classes) - - } else { - fail("Not an Element $grandChild") - } - val child = doc["child"].firstOrNull() - if (child != null) { - val gc1 = child.childElements("grandChild") - assertEquals(1, gc1.size(), "Expected a single child but found $gc1") - val gc2 = child.childElements("grandChild2") - assertEquals(1, gc2.size(), "Expected a single child but found $gc2") - } else { - fail("No child found!") - } - val children = doc.documentElement.children() - assertEquals(1, children.size()) - - } -} diff --git a/libraries/stdlib/test/dom/DomTest.kt b/libraries/stdlib/test/dom/DomTest.kt deleted file mode 100644 index b990228b217..00000000000 --- a/libraries/stdlib/test/dom/DomTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -package test.dom - -import kotlin.* -import kotlin.dom.* -import kotlin.test.* -import org.w3c.dom.* -import org.junit.Test as test - -class DomTest { - - @test fun testCreateDocument() { - var doc = createDocument() - assertNotNull(doc, "Should have created a document") - - val e = doc.createElement("foo")!! - assertCssClass(e, "") - - // now lets update the cssClass property - e.classes = "foo" - assertCssClass(e, "foo") - - // now using the attribute directly - e.setAttribute("class", "bar") - assertCssClass(e, "bar") - - doc + e - println("document ${doc.toXmlString()}") - } - - @test fun addText() { - var doc = createDocument() - assertNotNull(doc, "Should have created a document") - - val e = doc.createElement("foo")!! - e + "hello" - - val xml = e.toXmlString() - println("element after text ${xml}") - - assertEquals("hello", e.textContent) - - } - - - fun assertCssClass(e: Element, value: String?): Unit { - val cl = e.classes - val cl2 = e.getAttribute("class") - val xml = e.toXmlString() - println("element ${xml} has cssClass `${cl}` class attr `${cl2}`") - - assertEquals(value, cl, "value of element.cssClass") - assertEquals(value, cl2, "value of element.getAttribute(\"class\")") - } -} diff --git a/libraries/stdlib/test/dom/NextSiblingTest.kt b/libraries/stdlib/test/dom/NextSiblingTest.kt deleted file mode 100644 index da057245394..00000000000 --- a/libraries/stdlib/test/dom/NextSiblingTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package test.dom - -import kotlin.dom.* -import kotlin.test.* -import org.w3c.dom.* -import org.junit.Test as test - -class NextSiblingTest { - - @test fun nextSibling() { - val doc = createDocument() - - doc.addElement("foo") { - id = "id1" - style = "bold" - classes = "bar" - addElement("child") { - id = "id2" - classes = "another" - addElement("grandChild") { - id = "id3" - classes = " bar tiny" - addText("Hello World!") - // TODO support neater syntax sugar for adding text? - // += "Hello World!" - } - addElement("grandChild2") { - id = "id4" - classes = "tiny thing bar " - addText("Hello World!") - // TODO support neater syntax sugar for adding text? - // += "Hello World!" - } - } - } - - println("builder document: ${doc.toXmlString()}") - - - val elems = doc["#id3"] - val element = elems.first() - val elements = element.nextElements() - val nodes = element.nextSiblings().toList() - - assertEquals(1, elements.size()) - assertEquals(1, nodes.size()) - } -} diff --git a/libraries/stdlib/test/js/JsDomTest.kt b/libraries/stdlib/test/js/JsDomTest.kt deleted file mode 100644 index 899f7175edc..00000000000 --- a/libraries/stdlib/test/js/JsDomTest.kt +++ /dev/null @@ -1,155 +0,0 @@ -package test.js - -import kotlin.* -import kotlin.browser.* -import kotlin.dom.* -import kotlin.test.* -import org.w3c.dom.* -import org.junit.Test as test - -class JsDomTest { - - @test fun testCreateDocument() { - var doc = document - assertNotNull(doc, "Should have created a document") - - val e = doc.createElement("foo")!! - assertCssClass(e, "") - - // now lets update the cssClass property - e.classes = "foo" - assertCssClass(e, "foo") - - // now using the attribute directly - e.setAttribute("class", "bar") - assertCssClass(e, "bar") - } - - @test fun addText() { - var doc = document - assertNotNull(doc, "Should have created a document") - - val e = doc.createElement("foo")!! - e + "hello" - - val xml = e.toXmlString() - println("element after text ${xml}") - - assertEquals("hello", e.textContent) - } - - @test fun testAddClassMissing() { - val e = document.createElement("e")!! - assertNotNull(e) - - e.classes = "class1" - - e.addClass("class1", "class2") - - assertEquals("class1 class2", e.classes) - } - - @test fun testAddClassPresent() { - val e = document.createElement("e")!! - assertNotNull(e) - - e.classes = "class2 class1" - - e.addClass("class1", "class2") - - assertEquals("class2 class1", e.classes) - } - - @test fun testAddClassUndefinedClasses() { - val e = document.createElement("e")!! - e.addClass("class1") - assertEquals("class1", e.classes) - } - - @test fun testRemoveClassMissing() { - val e = document.createElement("e")!! - assertNotNull(e) - - e.classes = "class2 class1" - - e.removeClass("class3") - - assertEquals("class2 class1", e.classes) - } - - @test fun testRemoveClassPresent1() { - val e = document.createElement("e")!! - assertNotNull(e) - - e.classes = "class2 class1" - - e.removeClass("class2") - - assertEquals("class1", e.classes) - } - - @test fun testRemoveClassPresent2() { - val e = document.createElement("e")!! - assertNotNull(e) - - e.classes = "class2 class1" - - e.removeClass("class1") - - assertEquals("class2", e.classes) - } - - @test fun testRemoveClassPresent3() { - val e = document.createElement("e")!! - assertNotNull(e) - - e.classes = "class2 class1 class3" - - e.removeClass("class1") - - assertEquals("class2 class3", e.classes) - } - - @test fun testRemoveClassUndefinedClasses() { - val e = document.createElement("e")!! - e.removeClass("class1") - assertEquals("", e.classes) - } - - @test fun testRemoveFromParent() { - val doc = document - - val parent = doc.createElement("pp") - val child = doc.createElement("cc") - parent.appendChild(child) - - assertEquals(parent, child.parentNode) - assertEquals(listOf(child), parent.childNodes.asList()) - - child.removeFromParent() - - assertNull(child.parentNode) - assertEquals(emptyList(), parent.childNodes.asList()) - - child.removeFromParent() - assertNull(child.parentNode) - } - - @test fun testRemoveFromParentOrphanNode() { - val child = document.createElement("cc") - - child.removeFromParent() - - assertNull(child.parentNode) - } - - private fun assertCssClass(e: Element, value: String?): Unit { - val cl = e.classes - val cl2 = e.getAttribute("class") ?: "" - val xml = e.toXmlString() - println("element ${xml} has cssClass `${cl}` class attr `${cl2}`") - - assertEquals(value, cl, "value of element.cssClass") - assertEquals(value, cl2, "value of element.getAttribute(\"class\")") - } -}