making progress on porting kotlin/dom to JS; added AbstractList and RuntimeException/UnsupportedOperationException support to the kotlin-lib.js and fixed up a gremlin (Iterator is a trait not a class)
This commit is contained in:
@@ -16,7 +16,7 @@ public fun comparator<T>(f : (T, T) -> Int) : Comparator<T> = js.noImpl
|
|||||||
|
|
||||||
|
|
||||||
library
|
library
|
||||||
public open class Iterator<T>() {
|
public trait Iterator<T> {
|
||||||
open fun next() : T = js.noImpl
|
open fun next() : T = js.noImpl
|
||||||
open fun hasNext() : Boolean = js.noImpl
|
open fun hasNext() : Boolean = js.noImpl
|
||||||
open fun remove() : Unit = js.noImpl
|
open fun remove() : Unit = js.noImpl
|
||||||
@@ -67,6 +67,14 @@ public trait Collection<erased E> : java.lang.Iterable<E> {
|
|||||||
open fun clear() : Unit
|
open fun clear() : Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
library
|
||||||
|
public abstract open class AbstractCollection<erased E> : Collection<E> {
|
||||||
|
}
|
||||||
|
|
||||||
|
library
|
||||||
|
public abstract open class AbstractList<erased E> : AbstractCollection<E>, List<E> {
|
||||||
|
}
|
||||||
|
|
||||||
library
|
library
|
||||||
public trait List<erased E> : Collection<E> {
|
public trait List<erased E> : Collection<E> {
|
||||||
override fun size() : Int
|
override fun size() : Int
|
||||||
|
|||||||
@@ -286,14 +286,16 @@ var Kotlin;
|
|||||||
|
|
||||||
Kotlin.Exceptions = {};
|
Kotlin.Exceptions = {};
|
||||||
Kotlin.Exception = Kotlin.Class.create();
|
Kotlin.Exception = Kotlin.Class.create();
|
||||||
|
Kotlin.RuntimeException = Kotlin.Class.create(Kotlin.Exception);
|
||||||
Kotlin.Exceptions.IndexOutOfBounds = Kotlin.Class.create(Kotlin.Exception);
|
Kotlin.Exceptions.IndexOutOfBounds = Kotlin.Class.create(Kotlin.Exception);
|
||||||
Kotlin.Exceptions.NullPointerException = Kotlin.Class.create(Kotlin.Exception);
|
Kotlin.Exceptions.NullPointerException = Kotlin.Class.create(Kotlin.Exception);
|
||||||
|
Kotlin.Exceptions.UnsupportedOperationException = Kotlin.Class.create(Kotlin.Exception);
|
||||||
|
Kotlin.Exceptions.NoSuchElementException = Kotlin.Class.create(Kotlin.Exception);
|
||||||
|
|
||||||
Kotlin.throwNPE = function() {
|
Kotlin.throwNPE = function() {
|
||||||
throw new Kotlin.Exceptions.NullPointerException();
|
throw new Kotlin.Exceptions.NullPointerException();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Kotlin.ArrayList = Class.create({
|
Kotlin.ArrayList = Class.create({
|
||||||
initialize:function () {
|
initialize:function () {
|
||||||
this.array = [];
|
this.array = [];
|
||||||
@@ -358,6 +360,50 @@ var Kotlin;
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Kotlin.AbstractList = Class.create({
|
||||||
|
set:function (index, value) {
|
||||||
|
throw new Kotlin.Exceptions.UnsupportedOperationException();
|
||||||
|
},
|
||||||
|
iterator:function () {
|
||||||
|
return new Kotlin.ArrayIterator(this);
|
||||||
|
},
|
||||||
|
isEmpty:function () {
|
||||||
|
return (this.size() === 0);
|
||||||
|
},
|
||||||
|
add:function (element) {
|
||||||
|
throw new Kotlin.Exceptions.UnsupportedOperationException();
|
||||||
|
},
|
||||||
|
addAll:function (collection) {
|
||||||
|
var it = collection.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
this.add(it.next());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
remove:function(value) {
|
||||||
|
for (var i = 0; i < this.$size; ++i) {
|
||||||
|
if (this.array[i] == value) {
|
||||||
|
this.removeByIndex(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeByIndex:function (index) {
|
||||||
|
throw new Kotlin.Exceptions.UnsupportedOperationException();
|
||||||
|
},
|
||||||
|
clear:function () {
|
||||||
|
throw new Kotlin.Exceptions.UnsupportedOperationException();
|
||||||
|
},
|
||||||
|
contains:function (obj) {
|
||||||
|
for (var i = 0; i < this.$size; ++i) {
|
||||||
|
if (Kotlin.equals(this.array[i], obj)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
Kotlin.parseInt = function (str) {
|
Kotlin.parseInt = function (str) {
|
||||||
return parseInt(str, 10);
|
return parseInt(str, 10);
|
||||||
}
|
}
|
||||||
@@ -444,6 +490,7 @@ var Kotlin;
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Kotlin.RangeIterator = Kotlin.Class.create(Kotlin.Iterator, {
|
Kotlin.RangeIterator = Kotlin.Class.create(Kotlin.Iterator, {
|
||||||
initialize:function (start, count, reversed) {
|
initialize:function (start, count, reversed) {
|
||||||
this.$start = start;
|
this.$start = start;
|
||||||
|
|||||||
@@ -76,52 +76,8 @@ set(value) {
|
|||||||
this.setAttribute("class", value)
|
this.setAttribute("class", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
var Element.classSet : Set<String>
|
|
||||||
get() {
|
|
||||||
val answer = LinkedHashSet<String>()
|
|
||||||
val array = this.classes.split("""\s""")
|
|
||||||
for (s in array) {
|
|
||||||
if (s != null && s.size > 0) {
|
|
||||||
answer.add(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return answer
|
|
||||||
}
|
|
||||||
set(value) {
|
|
||||||
this.classes = value.makeString(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
|
|
||||||
/** Returns true if the element has the given CSS class style in its 'class' attribute */
|
|
||||||
fun Element.hasClass(cssClass: String): Boolean {
|
|
||||||
val c = this.classes
|
|
||||||
return if (c != null)
|
|
||||||
c.matches("""(^|.*\s+)$cssClass($|\s+.*)""")
|
|
||||||
else false
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds the given CSS class to this element's 'class' attribute */
|
|
||||||
fun Element.addClass(cssClass: String): Boolean {
|
|
||||||
val classSet = this.classSet
|
|
||||||
val answer = classSet.add(cssClass)
|
|
||||||
if (answer) {
|
|
||||||
this.classSet = classSet
|
|
||||||
}
|
|
||||||
return answer
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Removes the given CSS class to this element's 'class' attribute */
|
|
||||||
fun Element.removeClass(cssClass: String): Boolean {
|
|
||||||
val classSet = this.classSet
|
|
||||||
val answer = classSet.remove(cssClass)
|
|
||||||
if (answer) {
|
|
||||||
this.classSet = classSet
|
|
||||||
}
|
|
||||||
return answer
|
|
||||||
}
|
|
||||||
|
|
||||||
/** TODO this approach generates compiler errors...
|
/** TODO this approach generates compiler errors...
|
||||||
|
|
||||||
fun Element.addClass(varargs cssClasses: Array<String>): Boolean {
|
fun Element.addClass(varargs cssClasses: Array<String>): Boolean {
|
||||||
@@ -153,48 +109,39 @@ fun Element.removeClass(varargs cssClasses: Array<String>): Boolean {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */
|
class NodeListAsList(val nodeList: NodeList): AbstractList<Node>() {
|
||||||
fun Document?.get(selector: String): List<Element> {
|
override fun get(index: Int): Node {
|
||||||
val root = this?.getDocumentElement()
|
val node = nodeList.item(index)
|
||||||
return if (root != null) {
|
if (node == null) {
|
||||||
if (selector == "*") {
|
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
||||||
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)
|
|
||||||
Collections.singletonList(element).sure() as List<Element>
|
|
||||||
else
|
|
||||||
Collections.EMPTY_LIST.sure() as List<Element>
|
|
||||||
} else {
|
} else {
|
||||||
// assume its a vanilla element name
|
return node
|
||||||
elements(selector)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Collections.EMPTY_LIST as List<Element>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun size(): Int = nodeList.getLength()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */
|
class ElementListAsList(val nodeList: NodeList): AbstractList<Element>() {
|
||||||
fun Element.get(selector: String): List<Element> {
|
override fun get(index: Int): Element {
|
||||||
return if (selector == "*") {
|
val node = nodeList.item(index)
|
||||||
elements
|
if (node is Element) {
|
||||||
} else if (selector.startsWith(".")) {
|
return node
|
||||||
elements.filter{ it.hasClass(selector.substring(1)) }.toList()
|
} else {
|
||||||
} else if (selector.startsWith("#")) {
|
if (node == null) {
|
||||||
val element = this.getOwnerDocument()?.getElementById(selector.substring(1))
|
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
||||||
return if (element != null)
|
} else {
|
||||||
Collections.singletonList(element).sure() as List<Element>
|
throw IllegalArgumentException("Node is not an Element as expected but is $node")
|
||||||
else
|
}
|
||||||
Collections.EMPTY_LIST.sure() as List<Element>
|
}
|
||||||
} else {
|
|
||||||
// assume its a vanilla element name
|
|
||||||
elements(selector)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun size(): Int = nodeList.getLength()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns an [[Iterator]] over the next siblings of this node */
|
/** Returns an [[Iterator]] over the next siblings of this node */
|
||||||
fun Node.nextSiblings() : Iterator<Node> = NextSiblingIterator(this)
|
fun Node.nextSiblings() : Iterator<Node> = NextSiblingIterator(this)
|
||||||
|
|
||||||
@@ -229,55 +176,20 @@ class PreviousSiblingIterator(var node: Node) : AbstractIterator<Node>() {
|
|||||||
|
|
||||||
/** Returns true if this node is a Text node or a CDATA node */
|
/** Returns true if this node is a Text node or a CDATA node */
|
||||||
fun Node.isText(): Boolean {
|
fun Node.isText(): Boolean {
|
||||||
|
/*
|
||||||
|
This code is easier to convert to JS
|
||||||
val nodeType = getNodeType()
|
val nodeType = getNodeType()
|
||||||
return nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE
|
return nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE
|
||||||
|
*/
|
||||||
|
return this is Text || this is CDATASection
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns an [[Iterator]] of all the next [[Element]] siblings */
|
|
||||||
fun Node.nextElements(): Iterator<Element> = nextSiblings().filterIsInstance<Node, Element>(javaClass<Element>())
|
|
||||||
|
|
||||||
/** Returns an [[Iterator]] of all the previous [[Element]] siblings */
|
|
||||||
fun Node.previousElements(): Iterator<Element> = previousSiblings().filterIsInstance<Node, Element>(javaClass<Element>())
|
|
||||||
|
|
||||||
/** Returns the attribute value or empty string if its not present */
|
/** Returns the attribute value or empty string if its not present */
|
||||||
inline fun Element.attribute(name: String): String {
|
inline fun Element.attribute(name: String): String {
|
||||||
return this.getAttribute(name) ?: ""
|
return this.getAttribute(name) ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the children of the element as a list */
|
|
||||||
inline fun Element?.children(): List<Node> {
|
|
||||||
return this?.getChildNodes().toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The child elements of this document */
|
|
||||||
val Document?.elements : List<Element>
|
|
||||||
get() = this?.getElementsByTagName("*").toElementList()
|
|
||||||
|
|
||||||
/** The child elements of this elements */
|
|
||||||
val Element?.elements : List<Element>
|
|
||||||
get() = this?.getElementsByTagName("*").toElementList()
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns all the child elements given the local element name */
|
|
||||||
inline fun Element?.elements(localName: String?): List<Element> {
|
|
||||||
return this?.getElementsByTagName(localName).toElementList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns all the elements given the local element name */
|
|
||||||
inline fun Document?.elements(localName: String?): List<Element> {
|
|
||||||
return this?.getElementsByTagName(localName).toElementList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns all the child elements given the namespace URI and local element name */
|
|
||||||
inline fun Element?.elements(namespaceUri: String?, localName: String?): List<Element> {
|
|
||||||
return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns all the elements given the namespace URI and local element name */
|
|
||||||
inline fun Document?.elements(namespaceUri: String?, localName: String?): List<Element> {
|
|
||||||
return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val NodeList?.head : Node?
|
val NodeList?.head : Node?
|
||||||
get() = if (this != null && this.getLength() > 0) this.item(0) else null
|
get() = if (this != null && this.getLength() > 0) this.item(0) else null
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,135 @@ import javax.xml.transform.stream.StreamResult
|
|||||||
import org.w3c.dom.*
|
import org.w3c.dom.*
|
||||||
import org.xml.sax.InputSource
|
import org.xml.sax.InputSource
|
||||||
|
|
||||||
|
/** Returns the children of the element as a list */
|
||||||
|
inline fun Element?.children(): List<Node> {
|
||||||
|
return this?.getChildNodes().toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns an [[Iterator]] of all the next [[Element]] siblings */
|
||||||
|
fun Node.nextElements(): Iterator<Element> = nextSiblings().filterIsInstance<Node, Element>(javaClass<Element>())
|
||||||
|
|
||||||
|
/** Returns an [[Iterator]] of all the previous [[Element]] siblings */
|
||||||
|
fun Node.previousElements(): Iterator<Element> = previousSiblings().filterIsInstance<Node, Element>(javaClass<Element>())
|
||||||
|
|
||||||
|
|
||||||
|
/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */
|
||||||
|
fun Document?.get(selector: String): List<Element> {
|
||||||
|
val root = this?.getDocumentElement()
|
||||||
|
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)
|
||||||
|
Collections.singletonList(element).sure() as List<Element>
|
||||||
|
else
|
||||||
|
Collections.EMPTY_LIST.sure() as List<Element>
|
||||||
|
} else {
|
||||||
|
// assume its a vanilla element name
|
||||||
|
elements(selector)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Collections.EMPTY_LIST as List<Element>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */
|
||||||
|
fun Element.get(selector: String): List<Element> {
|
||||||
|
return if (selector == "*") {
|
||||||
|
elements
|
||||||
|
} else if (selector.startsWith(".")) {
|
||||||
|
elements.filter{ it.hasClass(selector.substring(1)) }.toList()
|
||||||
|
} else if (selector.startsWith("#")) {
|
||||||
|
val element = this.getOwnerDocument()?.getElementById(selector.substring(1))
|
||||||
|
return if (element != null)
|
||||||
|
Collections.singletonList(element).sure() as List<Element>
|
||||||
|
else
|
||||||
|
Collections.EMPTY_LIST.sure() as List<Element>
|
||||||
|
} else {
|
||||||
|
// assume its a vanilla element name
|
||||||
|
elements(selector)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The child elements of this document */
|
||||||
|
val Document?.elements : List<Element>
|
||||||
|
get() = this?.getElementsByTagName("*").toElementList()
|
||||||
|
|
||||||
|
/** The child elements of this elements */
|
||||||
|
val Element?.elements : List<Element>
|
||||||
|
get() = this?.getElementsByTagName("*").toElementList()
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns all the child elements given the local element name */
|
||||||
|
inline fun Element?.elements(localName: String?): List<Element> {
|
||||||
|
return this?.getElementsByTagName(localName).toElementList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns all the elements given the local element name */
|
||||||
|
inline fun Document?.elements(localName: String?): List<Element> {
|
||||||
|
return this?.getElementsByTagName(localName).toElementList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns all the child elements given the namespace URI and local element name */
|
||||||
|
inline fun Element?.elements(namespaceUri: String?, localName: String?): List<Element> {
|
||||||
|
return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns all the elements given the namespace URI and local element name */
|
||||||
|
inline fun Document?.elements(namespaceUri: String?, localName: String?): List<Element> {
|
||||||
|
return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var Element.classSet : Set<String>
|
||||||
|
get() {
|
||||||
|
val answer = LinkedHashSet<String>()
|
||||||
|
val array = this.classes.split("""\s""")
|
||||||
|
for (s in array) {
|
||||||
|
if (s != null && s.size > 0) {
|
||||||
|
answer.add(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return answer
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
this.classes = value.makeString(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true if the element has the given CSS class style in its 'class' attribute */
|
||||||
|
fun Element.hasClass(cssClass: String): Boolean {
|
||||||
|
val c = this.classes
|
||||||
|
return if (c != null)
|
||||||
|
c.matches("""(^|.*\s+)$cssClass($|\s+.*)""")
|
||||||
|
else false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds the given CSS class to this element's 'class' attribute */
|
||||||
|
fun Element.addClass(cssClass: String): Boolean {
|
||||||
|
val classSet = this.classSet
|
||||||
|
val answer = classSet.add(cssClass)
|
||||||
|
if (answer) {
|
||||||
|
this.classSet = classSet
|
||||||
|
}
|
||||||
|
return answer
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Removes the given CSS class to this element's 'class' attribute */
|
||||||
|
fun Element.removeClass(cssClass: String): Boolean {
|
||||||
|
val classSet = this.classSet
|
||||||
|
val answer = classSet.remove(cssClass)
|
||||||
|
if (answer) {
|
||||||
|
this.classSet = classSet
|
||||||
|
}
|
||||||
|
return answer
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Converts the node list to an XML String */
|
/** Converts the node list to an XML String */
|
||||||
fun NodeList?.toXmlString(xmlDeclaration: Boolean = false): String {
|
fun NodeList?.toXmlString(xmlDeclaration: Boolean = false): String {
|
||||||
return if (this == null)
|
return if (this == null)
|
||||||
@@ -45,37 +174,6 @@ inline fun NodeList?.toElementList(): List<Element> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NodeListAsList(val nodeList: NodeList): AbstractList<Node>() {
|
|
||||||
override fun get(index: Int): Node {
|
|
||||||
val node = nodeList.item(index)
|
|
||||||
if (node == null) {
|
|
||||||
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
|
||||||
} else {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun size(): Int = nodeList.getLength()
|
|
||||||
}
|
|
||||||
|
|
||||||
class ElementListAsList(val nodeList: NodeList): AbstractList<Element>() {
|
|
||||||
override fun get(index: Int): Element {
|
|
||||||
val node = nodeList.item(index)
|
|
||||||
if (node is Element) {
|
|
||||||
return node
|
|
||||||
} else {
|
|
||||||
if (node == null) {
|
|
||||||
throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index)
|
|
||||||
} else {
|
|
||||||
throw IllegalArgumentException("Node is not an Element as expected but is $node")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun size(): Int = nodeList.getLength()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a new document with the given document builder*/
|
/** Creates a new document with the given document builder*/
|
||||||
public fun createDocument(builder: DocumentBuilder): Document {
|
public fun createDocument(builder: DocumentBuilder): Document {
|
||||||
return builder.newDocument().sure()
|
return builder.newDocument().sure()
|
||||||
|
|||||||
Reference in New Issue
Block a user