From 41c980bcab0370ae42ab2b88383e44a72abb81d6 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 7 Feb 2017 21:45:38 +0300 Subject: [PATCH] Massive deprecations in kotlin.dom --- js/js.libraries/src/dom/Builder.kt | 28 +++----- js/js.libraries/src/dom/Builders.kt | 35 ++++++++++ js/js.libraries/src/dom/Dom.kt | 88 ++++++++++++++++-------- js/js.libraries/src/dom/DomEvents.kt | 19 +++-- js/js.libraries/src/dom/DomJS.kt | 7 +- js/js.libraries/src/dom/EventListener.kt | 26 +++++++ js/js.libraries/src/dom/Mutations.kt | 21 ++++-- 7 files changed, 159 insertions(+), 65 deletions(-) create mode 100644 js/js.libraries/src/dom/Builders.kt create mode 100644 js/js.libraries/src/dom/EventListener.kt diff --git a/js/js.libraries/src/dom/Builder.kt b/js/js.libraries/src/dom/Builder.kt index fb5f5a8b79f..b7342b4dd21 100644 --- a/js/js.libraries/src/dom/Builder.kt +++ b/js/js.libraries/src/dom/Builder.kt @@ -6,36 +6,26 @@ 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 -} +@Deprecated("Moved to kotlin.dom package", ReplaceWith("createElement(name, init)", "kotlin.dom.createElement"), level = DeprecationLevel.ERROR) +public fun Document.createElement(name: String, init: Element.() -> Unit): Element = createElement(name).apply(init) /** * 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 -} +@Deprecated("Use Document.createElement instead", level = DeprecationLevel.ERROR) +fun Element.createElement(name: String, doc: Document? = null, init: Element.() -> Unit): Element = ownerDocument!!.createElement(name).apply(init) /** * Adds a newly created element which can be configured via a function */ +@Deprecated("Use Element.appendElement instead.", level = DeprecationLevel.ERROR) fun Document.addElement(name: String, init: Element.() -> Unit): Element { - val child = createElement(name, init) + val child = createElement(name).apply(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 -} +@Deprecated("Use Element.appendElement instead", ReplaceWith("appendElement(name, init)", "kotlin.dom.appendElement"), level = DeprecationLevel.ERROR) +fun Element.addElement(name: String, doc: Document? = null, init: Element.() -> Unit): Element = appendElement(name, init) + diff --git a/js/js.libraries/src/dom/Builders.kt b/js/js.libraries/src/dom/Builders.kt new file mode 100644 index 00000000000..5fb9823e2ac --- /dev/null +++ b/js/js.libraries/src/dom/Builders.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2017 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.* + +/** + * Creates a new element with the specified [name]. + * + * The element is initialized with the speicifed [init] function. + */ +public fun Document.createElement(name: String, init: Element.() -> Unit): Element = createElement(name).apply(init) + +/** + * Appends a newly created element with the specified [name] to this element. + * + * The element is initialized with the speicifed [init] function. + */ +public fun Element.appendElement(name: String, init: Element.() -> Unit): Element = + ownerDocument!!.createElement(name, init).also { appendChild(it) } + diff --git a/js/js.libraries/src/dom/Dom.kt b/js/js.libraries/src/dom/Dom.kt index d5aa07638f5..91e0d06eaac 100644 --- a/js/js.libraries/src/dom/Dom.kt +++ b/js/js.libraries/src/dom/Dom.kt @@ -13,59 +13,87 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +@file:Suppress("DEPRECATION_ERROR") package kotlin.dom import org.w3c.dom.* -import kotlin.dom.* import kotlin.collections.* -// Properties +// DEPRECATED in 1.1-RC, drop after 1.1 /** Returns the children of the element as a list */ +@Deprecated("Use childNodes() function with safe call", ReplaceWith("this?.childNodes()?.asList().orEmpty()", "org.w3c.dom.asList"), level = DeprecationLevel.ERROR) fun Element?.children(): List { return this?.childNodes?.asList() ?: emptyList() } /** Returns the child elements of this element */ +@Deprecated("Use childNodes() function with safe call and filter it after", level = DeprecationLevel.ERROR) fun Element?.childElements(): List = this?.childNodes?.filterElements() ?: emptyList() -/** Returns the child elements of this element with the given name */ +/** Returns the child elements of this element with the given name. */ +@Deprecated("Use childNodes() function with safe call and filter it after", level = DeprecationLevel.ERROR) fun Element?.childElements(name: String): List = this?.childNodes?.filterElements()?.filter { it.nodeName == name } ?: emptyList() -/** Returns all the descendant elements given the local element name */ +/** Returns all the descendant elements given the local element name. */ +@Deprecated("Use getElementsByTagName() instead", ReplaceWith("getElementsByTagName(localName).asList()", "org.w3c.dom.asList"), level = DeprecationLevel.ERROR) fun Element.elements(localName: String = "*"): List { - return this.getElementsByTagName(localName).asElementList() + return this.getElementsByTagName(localName).asList() } /** Returns all the descendant elements given the local element name */ @JsName("deprecated_document_elements") +@Deprecated("Use getElementsByTagName() function with safe call", ReplaceWith("this?.getElementsByTagName(localName)?.asList().orEmpty()", "org.w3c.dom.asList"), level = DeprecationLevel.ERROR) fun Document?.elements(localName: String = "*"): List { - return this?.getElementsByTagName(localName)?.asElementList() ?: 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() + return this?.elements(localName).orEmpty() +} + +/** Returns all the descendant elements given the namespace URI and local element name. */ +@Deprecated("Use getElementsByTagNameNS() function instead", ReplaceWith("this?.getElementsByTagNameNS(namespaceUri, localName)?.asList().orEmpty()", "org.w3c.dom.asList"), level = DeprecationLevel.ERROR) +public fun Element.elements(namespaceUri: String, localName: String): List { + return this.getElementsByTagNameNS(namespaceUri, localName).asList() } /** Returns all the descendant elements given the namespace URI and local element name */ +@Deprecated("Use getElementsByTagNameNS() function with safe call", ReplaceWith("this?.getElementsByTagNameNS(namespaceUri, localName)?.asList().orEmpty()", "org.w3c.dom.asList"), level = DeprecationLevel.ERROR) fun Document?.elements(namespaceUri: String, localName: String): List { - return this?.getElementsByTagNameNS(namespaceUri, localName)?.asElementList() ?: emptyList() + return this?.getElementsByTagNameNS(namespaceUri, localName)?.asList() ?: emptyList() } -fun NodeList.asList(): List = NodeListAsList(this) +// END OF DEPRECATED /** - * 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. + * Returns a view of this [NodeList] as a list of nodes. */ -fun NodeList.asElementList(): List = if (length == 0) emptyList() else ElementListAsList(this) +//@Deprecated(W) +public fun NodeList.asList(): List = NodeListAsList(this) -@Suppress("UNCHECKED_CAST") -fun List.filterElements(): List = filter { it.isElement } as List +/** + * Returns a view of this [NodeList] as a list of elements assuming that it contains only elements. + * + * An attempt to get an element with [List.get] indexed accessor of the returned list + * will result in [ClassCastException] being thrown if that node is not an element. + * + * If you want to get a snapshot filtered to contain elements only it's better to use [filterElements] function. + */ +@Deprecated("This API is going to be removed", level = DeprecationLevel.WARNING) +public fun NodeList.asElementList(): List = ElementListAsList(this) + +/** + * Returns a list containing only [Element] nodes. + */ +@Deprecated("Use filter function instead", ReplaceWith("filter { it.isElement } as List"), level = DeprecationLevel.ERROR) +public fun List.filterElements(): List { + @Suppress("UNCHECKED_CAST") + return filter { it.isElement } as List +} + +/** + * Returns a list containing only [Element] nodes. + */ +@Deprecated("Use filter function instead", ReplaceWith("asList().filter { it.isElement } as List", "org.w3c.dom.asList"), level = DeprecationLevel.ERROR) +public fun NodeList.filterElements(): List = asList().filterElements() -fun NodeList.filterElements(): List = asList().filterElements() private class NodeListAsList(private val delegate: NodeList) : AbstractList() { override val size: Int get() = delegate.length @@ -84,15 +112,16 @@ private class ElementListAsList(private val nodeList: NodeList) : AbstractList = NextSiblings(this) +/** Returns an [Iterator] over the next siblings of this node. */ +@Deprecated("This API is going to be removed", level = DeprecationLevel.ERROR) +public fun Node.nextSiblings(): Iterable = NextSiblings(this) private class NextSiblings(private var node: Node) : Iterable { override fun iterator(): Iterator = object : AbstractIterator() { @@ -108,8 +137,9 @@ private class NextSiblings(private var node: Node) : Iterable { } } -/** Returns an [Iterator] over the next siblings of this node */ -fun Node.previousSiblings(): Iterable = PreviousSiblings(this) +/** Returns an [Iterator] over the next siblings of this node. */ +@Deprecated("This API is going to be removed", level = DeprecationLevel.ERROR) +public fun Node.previousSiblings(): Iterable = PreviousSiblings(this) private class PreviousSiblings(private var node: Node) : Iterable { override fun iterator(): Iterator = object : AbstractIterator() { @@ -126,14 +156,14 @@ private class PreviousSiblings(private var node: Node) : Iterable { } /** - * it is *true* when [Node.nodeType] is TEXT_NODE or CDATA_SECTION_NODE + * Gets a value indicating whether this node is a TEXT_NODE or a CDATA_SECTION_NODE. */ -val Node.isText: Boolean +public val Node.isText: Boolean get() = nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE /** - * `true` if it's an element node + * Gets a value indicating whether this node is an [Element]. */ -val Node.isElement: Boolean +public val Node.isElement: Boolean get() = nodeType == Node.ELEMENT_NODE diff --git a/js/js.libraries/src/dom/DomEvents.kt b/js/js.libraries/src/dom/DomEvents.kt index 9c34c41324d..aed1abfcfad 100644 --- a/js/js.libraries/src/dom/DomEvents.kt +++ b/js/js.libraries/src/dom/DomEvents.kt @@ -1,3 +1,4 @@ +@file:Suppress("DEPRECATION_ERROR") package kotlin.dom import org.w3c.dom.* @@ -6,17 +7,10 @@ import org.w3c.dom.events.* /** * Turns an event handler function into an [EventListener] */ -public fun eventHandler(handler: (Event) -> Unit): EventListener { - return EventListenerHandler(handler) -} - -private class EventListenerHandler(private val handler: (Event) -> Unit) : EventListener { - public override fun handleEvent(e: Event) { - handler(e) - } - public override fun toString(): String = "EventListenerHandler($handler)" -} +@Deprecated("Use EventListener SAM-like constructor instead", ReplaceWith("EventListener(handler)", "org.w3c.dom.events.EventListener"), level = DeprecationLevel.ERROR) +public fun eventHandler(handler: (Event) -> Unit): EventListener = EventListener(handler) +@Deprecated("Use EventListener SAM-like constructor instead", ReplaceWith("EventListener(handler)", "org.w3c.dom.events.EventListener"), level = DeprecationLevel.ERROR) public fun mouseEventHandler(handler: (MouseEvent) -> Unit): EventListener { return eventHandler { e -> if (e is MouseEvent) { @@ -25,6 +19,7 @@ public fun mouseEventHandler(handler: (MouseEvent) -> Unit): EventListener { } } +@Deprecated("This API is going to be removed", level = DeprecationLevel.ERROR) public interface Closeable { public open fun close(): Unit } @@ -32,6 +27,7 @@ public interface Closeable { /** * Registers a handler on the named event */ +@Deprecated("This API is going to be removed", level = DeprecationLevel.ERROR) public fun Node.on(name: String, capture: Boolean, handler: (Event) -> Unit): Closeable? { return on(name, capture, eventHandler(handler)) } @@ -39,6 +35,7 @@ public fun Node.on(name: String, capture: Boolean, handler: (Event) -> Unit): Cl /** * Registers an [EventListener] on the named event */ +@Deprecated("This API is going to be removed", level = DeprecationLevel.ERROR) public fun Node?.on(name: String, capture: Boolean, listener: EventListener): Closeable? { // TODO: instanceof EventTarget is a very bad idea! // TODO: nullable target is a very bad idea! @@ -65,10 +62,12 @@ private class CloseableEventListener( public override fun toString(): String = "CloseableEventListener($target, $name)" } +@Deprecated("This API is going to be removed", level = DeprecationLevel.ERROR) public fun Node?.onClick(capture: Boolean = false, handler: (MouseEvent) -> Unit): Closeable? { return on("click", capture, mouseEventHandler(handler)) } +@Deprecated("This API is going to be removed", level = DeprecationLevel.ERROR) public fun Node?.onDoubleClick(capture: Boolean = false, handler: (MouseEvent) -> Unit): Closeable? { return on("dblclick", capture, mouseEventHandler(handler)) } \ No newline at end of file diff --git a/js/js.libraries/src/dom/DomJS.kt b/js/js.libraries/src/dom/DomJS.kt index 8125873d799..60e2fd97b0d 100644 --- a/js/js.libraries/src/dom/DomJS.kt +++ b/js/js.libraries/src/dom/DomJS.kt @@ -6,11 +6,15 @@ import org.w3c.dom.HTMLCollection import org.w3c.dom.HTMLElement /** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ +@Deprecated("Use querySelectorAll instead", level = DeprecationLevel.ERROR) +@Suppress("DEPRECATION_ERROR") 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 #) */ +@Deprecated("Use querySelectorAll instead", level = DeprecationLevel.ERROR) +@Suppress("DEPRECATION_ERROR") operator fun Element.get(selector: String): List { return querySelectorAll(selector).asList().filterElements() } @@ -25,6 +29,7 @@ private class HTMLCollectionListView(val collection: HTMLCollection) : AbstractL } } +//@Deprecated(W) public fun HTMLCollection.asList(): List = HTMLCollectionListView(this) private class DOMTokenListView(val delegate: DOMTokenList) : AbstractList() { @@ -37,5 +42,5 @@ private class DOMTokenListView(val delegate: DOMTokenList) : AbstractList = DOMTokenListView(this) -internal fun HTMLCollection.asElementList(): List = asList() diff --git a/js/js.libraries/src/dom/EventListener.kt b/js/js.libraries/src/dom/EventListener.kt new file mode 100644 index 00000000000..21a2eb38d72 --- /dev/null +++ b/js/js.libraries/src/dom/EventListener.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2010-2017 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.events + +public fun EventListener(handler: (Event) -> Unit): EventListener = EventListenerHandler(handler) + +private class EventListenerHandler(private val handler: (Event) -> Unit) : EventListener { + public override fun handleEvent(e: Event) { + handler(e) + } + public override fun toString(): String = "EventListenerHandler($handler)" +} diff --git a/js/js.libraries/src/dom/Mutations.kt b/js/js.libraries/src/dom/Mutations.kt index d31d475cabf..275dfc543b5 100644 --- a/js/js.libraries/src/dom/Mutations.kt +++ b/js/js.libraries/src/dom/Mutations.kt @@ -2,8 +2,8 @@ package kotlin.dom import org.w3c.dom.* -/** Removes all the children from this node */ -fun Node.clear() { +/** Removes all the children from this node. */ +public fun Node.clear() { while (hasChildNodes()) { removeChild(firstChild!!) } @@ -12,21 +12,27 @@ fun Node.clear() { /** * Removes this node from parent node. Does nothing if no parent node */ -fun Node.removeFromParent() { +@Deprecated("Use parentNode?.removeChild(this) instead.", ReplaceWith("this.also { it.parentNode?.removeChild(it) }"), level = DeprecationLevel.ERROR) +public fun Node.removeFromParent() { parentNode?.removeChild(this) } +@Deprecated("Use appendChild instead", ReplaceWith("appendChild(node)"), level = DeprecationLevel.ERROR) operator fun Node.plus(child: Node): Node { appendChild(child) return this } +@Deprecated("Use appendText instead", ReplaceWith("appendText(text)"), level = DeprecationLevel.ERROR) operator fun Element.plus(text: String): Element = appendText(text) + +@Deprecated("Use appendText instead", ReplaceWith("appendText(text)"), level = DeprecationLevel.ERROR) operator fun Element.plusAssign(text: String): Unit { appendText(text) } /** Returns the owner document of the element or uses the provided document */ +@Deprecated("Use ownerDocument property instead", ReplaceWith("this.ownerDocument ?: doc ?: error(\"no ownerDocument\")"), level = DeprecationLevel.ERROR) 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") @@ -34,16 +40,19 @@ fun Node.ownerDocument(doc: Document? = null): Document = when { /** - * Creates text node and append it to the element + * Creates text node and append it to the element. + * + * @returns this element */ -fun Element.appendText(text: String, doc: Document? = null): Element { - appendChild(ownerDocument(doc).createTextNode(text)) +fun Element.appendText(text: String): Element { + appendChild(ownerDocument!!.createTextNode(text)) return this } /** * Appends the node to the specified parent element */ +@Deprecated("Use parent.appendChild instead", ReplaceWith("this.let(parent::appendChild)"), level = DeprecationLevel.ERROR) fun Node.appendTo(parent: Element) { parent.appendChild(this) }