+
-
+
-
-
+
-
+
@@ -72,16 +146,16 @@
-
+
-
+
-
+
-
+
@@ -90,7 +164,7 @@
-
+
diff --git a/src/main/kotlin/nl/astraeus/komp/todo/Todo.kt b/src/main/kotlin/nl/astraeus/komp/todo/Todo.kt
index 73b0dce..c61509e 100644
--- a/src/main/kotlin/nl/astraeus/komp/todo/Todo.kt
+++ b/src/main/kotlin/nl/astraeus/komp/todo/Todo.kt
@@ -1,8 +1,10 @@
package nl.astraeus.komp.todo
import kotlinx.html.*
+import kotlinx.html.dom.create
import kotlinx.html.js.*
import nl.astraeus.komp.Komponent
+import nl.astraeus.komp.DomDiffer
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event
@@ -212,4 +214,38 @@
fun main(args: Array) {
Komponent.create(document.body!!, TodoApp(), true)
+
+ val el1 = document.create.div {
+ div {
+ div {
+ id = "id1"
+ span {
+ +"Test"
+ }
+ }
+ }
+ }
+
+ val el2 = document.create.div {
+ div {
+ id = "id1"
+ span {
+ +"Test"
+ }
+ input {
+ name = "bla"
+ }
+ }
+ }
+
+ // println("equals ${DomDiffer.match(el1, el2)}")
+
+ console.log("OLD", el1)
+ console.log("NEW", el2)
+
+ DomDiffer.replaceDiff(el2, el1)
+
+ console.log("OLD", el1)
+ console.log("NEW", el2)
}
+
diff --git a/web/js/kotlin/komp-todo.js b/web/js/kotlin/komp-todo.js
index fb1054b..6c78492 100644
--- a/web/js/kotlin/komp-todo.js
+++ b/web/js/kotlin/komp-todo.js
@@ -35,6 +35,9 @@
var footer = $module$kotlinx_html_js.kotlinx.html.footer_780ap1$;
var section_0 = $module$kotlinx_html_js.kotlinx.html.js.section_ceckl$;
var ArrayList_init_0 = Kotlin.kotlin.collections.ArrayList_init_ww73n8$;
+ var get_create = $module$kotlinx_html_js.kotlinx.html.dom.get_create_4wc2mh$;
+ var div_0 = $module$kotlinx_html_js.kotlinx.html.js.div_wkomt5$;
+ var komp = $module$komp.nl.astraeus.komp;
Selection.prototype = Object.create(Enum.prototype);
Selection.prototype.constructor = Selection;
TodoApp.prototype = Object.create(Komponent.prototype);
@@ -368,9 +371,43 @@
simpleName: 'TodoApp',
interfaces: [Komponent]
};
+ function main$lambda$lambda$lambda$lambda($receiver) {
+ $receiver.unaryPlus_pdl1vz$('Test');
+ }
+ function main$lambda$lambda$lambda($receiver) {
+ set_id($receiver, 'id1');
+ span($receiver, void 0, main$lambda$lambda$lambda$lambda);
+ }
+ function main$lambda$lambda($receiver) {
+ div($receiver, void 0, main$lambda$lambda$lambda);
+ }
+ function main$lambda($receiver) {
+ div($receiver, void 0, main$lambda$lambda);
+ }
+ function main$lambda$lambda$lambda_0($receiver) {
+ $receiver.unaryPlus_pdl1vz$('Test');
+ }
+ function main$lambda$lambda$lambda_1($receiver) {
+ $receiver.name = 'bla';
+ }
+ function main$lambda$lambda_0($receiver) {
+ set_id($receiver, 'id1');
+ span($receiver, void 0, main$lambda$lambda$lambda_0);
+ input($receiver, void 0, void 0, void 0, void 0, void 0, main$lambda$lambda$lambda_1);
+ }
+ function main$lambda_0($receiver) {
+ div($receiver, void 0, main$lambda$lambda_0);
+ }
function main(args) {
var tmp$;
Komponent.Companion.create_nkol39$((tmp$ = document.body) != null ? tmp$ : Kotlin.throwNPE(), new TodoApp(), true);
+ var el1 = div_0(get_create(document), void 0, main$lambda);
+ var el2 = div_0(get_create(document), void 0, main$lambda_0);
+ console.log('OLD', el1);
+ console.log('NEW', el2);
+ komp.DomDiffer.replaceDiff_aifv3w$(el2, el1);
+ console.log('OLD', el1);
+ console.log('NEW', el2);
}
var package$nl = _.nl || (_.nl = {});
var package$astraeus = package$nl.astraeus || (package$nl.astraeus = {});
diff --git a/web/js/kotlin/komp-todo.js.map b/web/js/kotlin/komp-todo.js.map
index eb1edfb..0b46f8b 100644
--- a/web/js/kotlin/komp-todo.js.map
+++ b/web/js/kotlin/komp-todo.js.map
@@ -1 +1 @@
-{"version":3,"file":"komp-todo.js","sources":["nl/astraeus/komp/todo/Todo.kt","collections/Maps.kt"],"sourcesContent":[null,"@file:kotlin.jvm.JvmMultifileClass\n@file:kotlin.jvm.JvmName(\"MapsKt\")\n\npackage kotlin.collections\n\nprivate object EmptyMap : Map, Serializable {\n private const val serialVersionUID: Long = 8246714829545688274\n\n override fun equals(other: Any?): Boolean = other is Map<*,*> && other.isEmpty()\n override fun hashCode(): Int = 0\n override fun toString(): String = \"{}\"\n\n override val size: Int get() = 0\n override fun isEmpty(): Boolean = true\n\n override fun containsKey(key: Any?): Boolean = false\n override fun containsValue(value: Nothing): Boolean = false\n override fun get(key: Any?): Nothing? = null\n override val entries: Set> get() = EmptySet\n override val keys: Set get() = EmptySet\n override val values: Collection get() = EmptyList\n\n private fun readResolve(): Any = EmptyMap\n}\n\n/**\n * Returns an empty read-only map of specified type.\n *\n * The returned map is serializable (JVM).\n * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap\n */\npublic fun emptyMap(): Map = @Suppress(\"UNCHECKED_CAST\") (EmptyMap as Map)\n\n/**\n * Returns a new read-only map with the specified contents, given as a list of pairs\n * where the first value is the key and the second is the value.\n *\n * If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.\n *\n * Entries of the map are iterated in the order they were specified.\n *\n * The returned map is serializable (JVM).\n *\n * @sample samples.collections.Maps.Instantiation.mapFromPairs\n */\npublic fun mapOf(vararg pairs: Pair): Map = if (pairs.size > 0) pairs.toMap(LinkedHashMap(mapCapacity(pairs.size))) else emptyMap()\n\n/**\n * Returns an empty read-only map.\n *\n * The returned map is serializable (JVM).\n * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap\n */\n@kotlin.internal.InlineOnly\npublic inline fun mapOf(): Map = emptyMap()\n\n/* Not available on platform: JS */\n\n\n\n\n\n\n\n\n\n\n/**\n * Returns an empty new [MutableMap].\n *\n * The returned map preserves the entry iteration order.\n * @sample samples.collections.Maps.Instantiation.emptyMutableMap\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline fun mutableMapOf(): MutableMap = LinkedHashMap()\n\n/**\n * Returns a new [MutableMap] with the specified contents, given as a list of pairs\n * where the first component is the key and the second is the value.\n *\n * If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.\n *\n * Entries of the map are iterated in the order they were specified.\n *\n * @sample samples.collections.Maps.Instantiation.mutableMapFromPairs\n * @sample samples.collections.Maps.Instantiation.emptyMutableMap\n */\npublic fun mutableMapOf(vararg pairs: Pair): MutableMap\n = LinkedHashMap(mapCapacity(pairs.size)).apply { putAll(pairs) }\n\n/**\n * Returns an empty new [HashMap].\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline fun hashMapOf(): HashMap = HashMap()\n\n/**\n * Returns a new [HashMap] with the specified contents, given as a list of pairs\n * where the first component is the key and the second is the value.\n *\n * @sample samples.collections.Maps.Instantiation.hashMapFromPairs\n */\npublic fun hashMapOf(vararg pairs: Pair): HashMap\n = HashMap(mapCapacity(pairs.size)).apply { putAll(pairs) }\n\n/**\n * Returns an empty new [LinkedHashMap].\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline fun linkedMapOf(): LinkedHashMap = LinkedHashMap()\n\n/**\n * Returns a new [LinkedHashMap] with the specified contents, given as a list of pairs\n * where the first component is the key and the second is the value.\n *\n * If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.\n *\n * Entries of the map are iterated in the order they were specified.\n *\n * @sample samples.collections.Maps.Instantiation.linkedMapFromPairs\n */\npublic fun linkedMapOf(vararg pairs: Pair): LinkedHashMap\n = pairs.toMap(LinkedHashMap(mapCapacity(pairs.size)))\n\n/**\n * Calculate the initial capacity of a map, based on Guava's com.google.common.collect.Maps approach. This is equivalent\n * to the Collection constructor for HashSet, (c.size()/.75f) + 1, but provides further optimisations for very small or\n * very large sizes, allows support non-collection classes, and provides consistency for all map based class construction.\n */\n@PublishedApi\ninternal fun mapCapacity(expectedSize: Int): Int {\n if (expectedSize < 3) {\n return expectedSize + 1\n }\n if (expectedSize < INT_MAX_POWER_OF_TWO) {\n return expectedSize + expectedSize / 3\n }\n return Int.MAX_VALUE // any large value\n}\n\nprivate const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1\n\n/** Returns `true` if this map is not empty. */\n@kotlin.internal.InlineOnly\npublic inline fun Map.isNotEmpty(): Boolean = !isEmpty()\n\n/**\n * Returns the [Map] if its not `null`, or the empty [Map] otherwise.\n */\n@kotlin.internal.InlineOnly\npublic inline fun Map?.orEmpty() : Map = this ?: emptyMap()\n\n/**\n * Checks if the map contains the given key.\n *\n * This method allows to use the `x in map` syntax for checking whether an object is contained in the map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.contains(key: K) : Boolean = containsKey(key)\n\n/**\n * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.get(key: K): V?\n = @Suppress(\"UNCHECKED_CAST\") (this as Map).get(key)\n\n/**\n * Allows to use the index operator for storing values in a mutable map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.set(key: K, value: V): Unit {\n put(key, value)\n}\n\n/**\n * Returns `true` if the map contains the specified [key].\n *\n * Allows to overcome type-safety restriction of `containsKey` that requires to pass a key of type `K`.\n */\n@kotlin.internal.InlineOnly\npublic inline fun <@kotlin.internal.OnlyInputTypes K> Map.containsKey(key: K): Boolean\n = @Suppress(\"UNCHECKED_CAST\") (this as Map).containsKey(key)\n\n/**\n * Returns `true` if the map maps one or more keys to the specified [value].\n *\n * Allows to overcome type-safety restriction of `containsValue` that requires to pass a value of type `V`.\n */\n@Suppress(\"EXTENSION_SHADOWED_BY_MEMBER\") // false warning, extension takes precedence in some cases\n@kotlin.internal.InlineOnly\npublic inline fun Map.containsValue(value: V): Boolean = this.containsValue(value)\n\n\n/**\n * Removes the specified key and its corresponding value from this map.\n *\n * @return the previous value associated with the key, or `null` if the key was not present in the map.\n\n * Allows to overcome type-safety restriction of `remove` that requires to pass a key of type `K`.\n */\n@kotlin.internal.InlineOnly\npublic inline fun <@kotlin.internal.OnlyInputTypes K, V> MutableMap.remove(key: K): V?\n = @Suppress(\"UNCHECKED_CAST\") (this as MutableMap).remove(key)\n\n/**\n * Returns the key component of the map entry.\n *\n * This method allows to use destructuring declarations when working with maps, for example:\n * ```\n * for ((key, value) in map) {\n * // do something with the key and the value\n * }\n * ```\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun Map.Entry.component1(): K = key\n\n/**\n * Returns the value component of the map entry.\n *\n * This method allows to use destructuring declarations when working with maps, for example:\n * ```\n * for ((key, value) in map) {\n * // do something with the key and the value\n * }\n * ```\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun Map.Entry.component2(): V = value\n\n/**\n * Converts entry to [Pair] with key being first component and value being second.\n */\n@kotlin.internal.InlineOnly\npublic inline fun Map.Entry.toPair(): Pair = Pair(key, value)\n\n/**\n * Returns the value for the given key, or the result of the [defaultValue] function if there was no entry for the given key.\n *\n * @sample samples.collections.Maps.Usage.getOrElse\n */\n@kotlin.internal.InlineOnly\npublic inline fun Map.getOrElse(key: K, defaultValue: () -> V): V = get(key) ?: defaultValue()\n\n\ninternal inline fun Map.getOrElseNullable(key: K, defaultValue: () -> V): V {\n val value = get(key)\n if (value == null && !containsKey(key)) {\n return defaultValue()\n } else {\n @Suppress(\"UNCHECKED_CAST\")\n return value as V\n }\n}\n\n/**\n * Returns the value for the given [key] or throws an exception if there is no such key in the map.\n *\n * If the map was created by [withDefault], resorts to its `defaultValue` provider function\n * instead of throwing an exception.\n *\n * @throws NoSuchElementException when the map doesn't contain a value for the specified key and\n * no implicit default value was provided for that map.\n */\n@SinceKotlin(\"1.1\")\npublic fun Map.getValue(key: K): V = getOrImplicitDefault(key)\n\n/**\n * Returns the value for the given key. If the key is not found in the map, calls the [defaultValue] function,\n * puts its result into the map under the given key and returns it.\n *\n * @sample samples.collections.Maps.Usage.getOrPut\n */\npublic inline fun MutableMap.getOrPut(key: K, defaultValue: () -> V): V {\n val value = get(key)\n return if (value == null) {\n val answer = defaultValue()\n put(key, answer)\n answer\n } else {\n value\n }\n}\n\n/**\n * Returns an [Iterator] over the entries in the [Map].\n *\n * @sample samples.collections.Maps.Usage.forOverEntries\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun Map.iterator(): Iterator> = entries.iterator()\n\n/* Not available on platform: JS */\n\n\n\n\n\n\n\n\n/**\n * Populates the given [destination] map with entries having the keys of this map and the values obtained\n * by applying the [transform] function to each entry in this [Map].\n */\npublic inline fun > Map.mapValuesTo(destination: M, transform: (Map.Entry) -> R): M {\n return entries.associateByTo(destination, { it.key }, transform)\n}\n\n/**\n * Populates the given [destination] map with entries having the keys obtained\n * by applying the [transform] function to each entry in this [Map] and the values of this map.\n *\n * In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite\n * the value associated with the former one.\n */\npublic inline fun > Map.mapKeysTo(destination: M, transform: (Map.Entry) -> R): M {\n return entries.associateByTo(destination, transform, { it.value })\n}\n\n/**\n * Puts all the given [pairs] into this [MutableMap] with the first component in the pair being the key and the second the value.\n */\npublic fun MutableMap.putAll(pairs: Array>): Unit {\n for ((key, value) in pairs) {\n put(key, value)\n }\n}\n\n/**\n * Puts all the elements of the given collection into this [MutableMap] with the first component in the pair being the key and the second the value.\n */\npublic fun MutableMap.putAll(pairs: Iterable>): Unit {\n for ((key, value) in pairs) {\n put(key, value)\n }\n}\n\n/**\n * Puts all the elements of the given sequence into this [MutableMap] with the first component in the pair being the key and the second the value.\n */\npublic fun MutableMap.putAll(pairs: Sequence>): Unit {\n for ((key, value) in pairs) {\n put(key, value)\n }\n}\n\n/**\n * Returns a new map with entries having the keys of this map and the values obtained by applying the [transform]\n * function to each entry in this [Map].\n *\n * The returned map preserves the entry iteration order of the original map.\n *\n * @sample samples.collections.Maps.Transforms.mapValues\n */\npublic inline fun Map.mapValues(transform: (Map.Entry) -> R): Map {\n return mapValuesTo(LinkedHashMap(mapCapacity(size)), transform) // .optimizeReadOnlyMap()\n}\n\n/**\n * Returns a new Map with entries having the keys obtained by applying the [transform] function to each entry in this\n * [Map] and the values of this map.\n *\n * In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite\n * the value associated with the former one.\n *\n * The returned map preserves the entry iteration order of the original map.\n *\n * @sample samples.collections.Maps.Transforms.mapKeys\n */\npublic inline fun Map.mapKeys(transform: (Map.Entry) -> R): Map {\n return mapKeysTo(LinkedHashMap(mapCapacity(size)), transform) // .optimizeReadOnlyMap()\n}\n\n/**\n * Returns a map containing all key-value pairs with keys matching the given [predicate].\n *\n * The returned map preserves the entry iteration order of the original map.\n */\npublic inline fun Map.filterKeys(predicate: (K) -> Boolean): Map {\n val result = LinkedHashMap()\n for (entry in this) {\n if (predicate(entry.key)) {\n result.put(entry.key, entry.value)\n }\n }\n return result\n}\n\n/**\n * Returns a map containing all key-value pairs with values matching the given [predicate].\n *\n * The returned map preserves the entry iteration order of the original map.\n */\npublic inline fun Map.filterValues(predicate: (V) -> Boolean): Map {\n val result = LinkedHashMap()\n for (entry in this) {\n if (predicate(entry.value)) {\n result.put(entry.key, entry.value)\n }\n }\n return result\n}\n\n\n/**\n * Appends all entries matching the given [predicate] into the mutable map given as [destination] parameter.\n *\n * @return the destination map.\n */\npublic inline fun > Map.filterTo(destination: M, predicate: (Map.Entry) -> Boolean): M {\n for (element in this) {\n if (predicate(element)) {\n destination.put(element.key, element.value)\n }\n }\n return destination\n}\n\n/**\n * Returns a new map containing all key-value pairs matching the given [predicate].\n *\n * The returned map preserves the entry iteration order of the original map.\n */\npublic inline fun Map.filter(predicate: (Map.Entry) -> Boolean): Map {\n return filterTo(LinkedHashMap(), predicate)\n}\n\n/**\n * Appends all entries not matching the given [predicate] into the given [destination].\n *\n * @return the destination map.\n */\npublic inline fun > Map.filterNotTo(destination: M, predicate: (Map.Entry) -> Boolean): M {\n for (element in this) {\n if (!predicate(element)) {\n destination.put(element.key, element.value)\n }\n }\n return destination\n}\n\n/**\n * Returns a new map containing all key-value pairs not matching the given [predicate].\n *\n * The returned map preserves the entry iteration order of the original map.\n */\npublic inline fun Map.filterNot(predicate: (Map.Entry) -> Boolean): Map {\n return filterNotTo(LinkedHashMap(), predicate)\n}\n\n/**\n * Returns a new map containing all key-value pairs from the given collection of pairs.\n *\n * The returned map preserves the entry iteration order of the original collection.\n */\npublic fun Iterable>.toMap(): Map {\n if (this is Collection) {\n return when (size) {\n 0 -> emptyMap()\n 1 -> mapOf(if (this is List) this[0] else iterator().next())\n else -> toMap(LinkedHashMap(mapCapacity(size)))\n }\n }\n return toMap(LinkedHashMap()).optimizeReadOnlyMap()\n}\n\n/**\n * Populates and returns the [destination] mutable map with key-value pairs from the given collection of pairs.\n */\npublic fun > Iterable>.toMap(destination: M): M\n = destination.apply { putAll(this@toMap) }\n\n/**\n * Returns a new map containing all key-value pairs from the given array of pairs.\n *\n * The returned map preserves the entry iteration order of the original array.\n */\npublic fun Array>.toMap(): Map = when(size) {\n 0 -> emptyMap()\n 1 -> mapOf(this[0])\n else -> toMap(LinkedHashMap(mapCapacity(size)))\n}\n\n/**\n * Populates and returns the [destination] mutable map with key-value pairs from the given array of pairs.\n */\npublic fun > Array>.toMap(destination: M): M\n = destination.apply { putAll(this@toMap) }\n\n/**\n * Returns a new map containing all key-value pairs from the given sequence of pairs.\n *\n * The returned map preserves the entry iteration order of the original sequence.\n */\npublic fun Sequence>.toMap(): Map = toMap(LinkedHashMap()).optimizeReadOnlyMap()\n\n/**\n * Populates and returns the [destination] mutable map with key-value pairs from the given sequence of pairs.\n */\npublic fun > Sequence>.toMap(destination: M): M\n = destination.apply { putAll(this@toMap) }\n\n/**\n * Returns a new read-only map containing all key-value pairs from the original map.\n *\n * The returned map preserves the entry iteration order of the original map.\n */\n@SinceKotlin(\"1.1\")\npublic fun Map.toMap(): Map = when (size) {\n 0 -> emptyMap()\n 1 -> toSingletonMap()\n else -> toMutableMap()\n}\n\n/**\n * Returns a new mutable map containing all key-value pairs from the original map.\n *\n * The returned map preserves the entry iteration order of the original map.\n */\n@SinceKotlin(\"1.1\")\npublic fun Map.toMutableMap(): MutableMap = LinkedHashMap(this)\n\n/**\n * Populates and returns the [destination] mutable map with key-value pairs from the given map.\n */\n@SinceKotlin(\"1.1\")\npublic fun > Map.toMap(destination: M): M\n = destination.apply { putAll(this@toMap) }\n\n/**\n * Creates a new read-only map by replacing or adding an entry to this map from a given key-value [pair].\n *\n * The returned map preserves the entry iteration order of the original map.\n * The [pair] is iterated in the end if it has a unique key.\n */\npublic operator fun Map.plus(pair: Pair): Map\n = if (this.isEmpty()) mapOf(pair) else LinkedHashMap(this).apply { put(pair.first, pair.second) }\n\n/**\n * Creates a new read-only map by replacing or adding entries to this map from a given collection of key-value [pairs].\n *\n * The returned map preserves the entry iteration order of the original map.\n * Those [pairs] with unique keys are iterated in the end in the order of [pairs] collection.\n */\npublic operator fun Map.plus(pairs: Iterable>): Map\n = if (this.isEmpty()) pairs.toMap() else LinkedHashMap(this).apply { putAll(pairs) }\n\n/**\n * Creates a new read-only map by replacing or adding entries to this map from a given array of key-value [pairs].\n *\n * The returned map preserves the entry iteration order of the original map.\n * Those [pairs] with unique keys are iterated in the end in the order of [pairs] array.\n */\npublic operator fun Map.plus(pairs: Array>): Map\n = if (this.isEmpty()) pairs.toMap() else LinkedHashMap(this).apply { putAll(pairs) }\n\n/**\n * Creates a new read-only map by replacing or adding entries to this map from a given sequence of key-value [pairs].\n *\n * The returned map preserves the entry iteration order of the original map.\n * Those [pairs] with unique keys are iterated in the end in the order of [pairs] sequence.\n */\npublic operator fun Map.plus(pairs: Sequence>): Map\n = LinkedHashMap(this).apply { putAll(pairs) }.optimizeReadOnlyMap()\n\n/**\n * Creates a new read-only map by replacing or adding entries to this map from another [map].\n *\n * The returned map preserves the entry iteration order of the original map.\n * Those entries of another [map] that are missing in this map are iterated in the end in the order of that [map].\n */\npublic operator fun Map.plus(map: Map): Map\n = LinkedHashMap(this).apply { putAll(map) }\n\n\n/**\n * Appends or replaces the given [pair] in this mutable map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.plusAssign(pair: Pair) {\n put(pair.first, pair.second)\n}\n\n/**\n * Appends or replaces all pairs from the given collection of [pairs] in this mutable map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.plusAssign(pairs: Iterable>) {\n putAll(pairs)\n}\n\n/**\n * Appends or replaces all pairs from the given array of [pairs] in this mutable map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.plusAssign(pairs: Array>) {\n putAll(pairs)\n}\n\n/**\n * Appends or replaces all pairs from the given sequence of [pairs] in this mutable map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.plusAssign(pairs: Sequence>) {\n putAll(pairs)\n}\n\n/**\n * Appends or replaces all entries from the given [map] in this mutable map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.plusAssign(map: Map) {\n putAll(map)\n}\n\n/**\n * Returns a map containing all entries of the original map except the entry with the given [key].\n *\n * The returned map preserves the entry iteration order of the original map.\n */\n@SinceKotlin(\"1.1\")\npublic operator fun Map.minus(key: K): Map\n = this.toMutableMap().apply { minusAssign(key) }.optimizeReadOnlyMap()\n\n/**\n * Returns a map containing all entries of the original map except those entries\n * the keys of which are contained in the given [keys] collection.\n *\n * The returned map preserves the entry iteration order of the original map.\n */\n@SinceKotlin(\"1.1\")\npublic operator fun Map.minus(keys: Iterable): Map\n = this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap()\n\n/**\n * Returns a map containing all entries of the original map except those entries\n * the keys of which are contained in the given [keys] array.\n *\n * The returned map preserves the entry iteration order of the original map.\n */\n@SinceKotlin(\"1.1\")\npublic operator fun Map.minus(keys: Array): Map\n = this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap()\n\n/**\n * Returns a map containing all entries of the original map except those entries\n * the keys of which are contained in the given [keys] sequence.\n *\n * The returned map preserves the entry iteration order of the original map.\n */\n@SinceKotlin(\"1.1\")\npublic operator fun Map.minus(keys: Sequence): Map\n = this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap()\n\n/**\n * Removes the entry with the given [key] from this mutable map.\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.minusAssign(key: K) {\n remove(key)\n}\n\n/**\n * Removes all entries the keys of which are contained in the given [keys] collection from this mutable map.\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.minusAssign(keys: Iterable) {\n this.keys.removeAll(keys)\n}\n\n/**\n * Removes all entries the keys of which are contained in the given [keys] array from this mutable map.\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.minusAssign(keys: Array) {\n this.keys.removeAll(keys)\n}\n\n/**\n * Removes all entries from the keys of which are contained in the given [keys] sequence from this mutable map.\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline operator fun MutableMap.minusAssign(keys: Sequence) {\n this.keys.removeAll(keys)\n}\n\n\n// do not expose for now @PublishedApi\ninternal fun Map.optimizeReadOnlyMap() = when (size) {\n 0 -> emptyMap()\n 1 -> toSingletonMapOrSelf()\n else -> this\n}\n\n/* Not available on platform: JS */\n\n\n\n\n/* Not available on platform: JS */\n\n\n\n"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"komp-todo.js","sources":["nl/astraeus/komp/todo/Todo.kt","collections/Maps.kt"],"sourcesContent":["package nl.astraeus.komp.todo\n\nimport kotlinx.html.*\nimport kotlinx.html.dom.create\nimport kotlinx.html.js.*\nimport nl.astraeus.komp.Komponent\nimport nl.astraeus.komp.DomDiffer\nimport org.w3c.dom.HTMLElement\nimport org.w3c.dom.HTMLInputElement\nimport org.w3c.dom.events.Event\nimport org.w3c.dom.events.KeyboardEvent\nimport kotlin.browser.document\nimport kotlin.js.Date\n\n/**\n * https://github.com/tastejs/todomvc/\n */\n\nclass Todo(\n val dataId: String,\n var title: String,\n var completed: Boolean = false,\n var editing: Boolean = false\n)\n\nenum class Selection(val title: String) {\n ALL(\"All\"),\n ACTIVE(\"Active\"),\n COMPLETED(\"Completed\")\n}\n\nclass TodoApp: Komponent() {\n val todoList: MutableList = ArrayList()\n var selected: Selection = Selection.ALL\n\n fun addTodo(e: Event) {\n val target = e.target\n\n if (target is HTMLInputElement) {\n todoList.add(Todo(\"${Date().getTime()}\", target.value))\n\n refresh()\n }\n }\n\n fun editTodo(e: Event, todo: Todo) {\n val target = e.target\n\n if (target is HTMLInputElement) {\n todo.title = target.value\n todo.editing = false\n\n refresh()\n }\n\n }\n\n fun destroyTodo(todo: Todo) {\n todoList.remove(todo)\n\n refresh()\n }\n\n fun selectSelection(selection: Selection) {\n selected = selection\n\n refresh()\n }\n\n fun clearCompleted() {\n for (todo in ArrayList(todoList)) {\n if (todo.completed) {\n todoList.remove(todo)\n }\n }\n\n refresh()\n }\n\n fun todoClicked(todo: Todo) {\n todo.completed = !todo.completed\n\n refresh()\n }\n\n fun getItemsLeft(): Int {\n var result = 0\n for (todo in todoList) {\n if (!todo.completed) {\n result++\n }\n }\n return result\n }\n\n fun setEditing(editTodo: Todo) {\n for (todo in todoList) {\n todo.editing = todo == editTodo\n }\n\n refresh()\n }\n\n override fun refresh() {\n super.refresh()\n\n val inputBox = document.getElementById(\"todo_input\")\n\n if (inputBox is HTMLInputElement) {\n inputBox.focus()\n }\n }\n\n override fun render(consumer: TagConsumer) = consumer.section(classes = \"todoapp\") {\n header(classes = \"header\") {\n h1 { + \"todos\" }\n input(classes = \"new-todo\") {\n id = \"todo_input\"\n placeholder = \"What needs to be done?\"\n autoFocus = true\n onKeyPressFunction = { e ->\n if (e is KeyboardEvent && e.keyCode == 13) {\n addTodo(e)\n }\n }\n }\n }\n\n section(classes = \"main\") {\n input(classes = \"toggle-all\") {\n type = InputType.checkBox\n }\n label {\n for_ = \"toggle-all\"\n + \"Mark all as complete\"\n }\n ul(classes = \"todo-list\") {\n for (todo in todoList) {\n if (selected == Selection.ALL ||\n (todo.completed && selected == Selection.COMPLETED) ||\n (!todo.completed && selected == Selection.ACTIVE)) {\n li {\n if (todo.editing) {\n classes += \"editing\"\n input(classes = \"edit\") {\n value = todo.title\n onKeyPressFunction = { e ->\n if (e is KeyboardEvent && e.keyCode == 13) {\n editTodo(e, todo)\n }\n }\n }\n } else {\n if (todo.completed) {\n classes += \"completed\"\n }\n attributes[\"data-id\"] = todo.dataId\n div(classes = \"view\") {\n input(classes = \"toggle\") {\n type = InputType.checkBox\n checked = todo.completed\n onClickFunction = {\n todoClicked(todo)\n }\n }\n label(classes = \"todo-content\") {\n +todo.title\n\n onDoubleClickFunction = {\n setEditing(todo)\n }\n }\n button(classes = \"destroy\") {\n onClickFunction = {\n destroyTodo(todo)\n }\n }\n }\n }\n }\n }\n }\n }\n }\n\n footer(classes = \"footer\") {\n span(classes = \"todo-count\") {\n strong { + \"${getItemsLeft()}\" }\n + \" item left\"\n }\n ul(classes = \"filters\") {\n for (selection in Selection.values())\n li {\n a {\n if (selection == selected) { classes += \"selected\" }\n href = \"#\"\n + selection.title\n onClickFunction = {\n selectSelection(selection)\n }\n }\n }\n }\n button(classes = \"clear-completed\") {\n + \"Clear completed\"\n onClickFunction = {\n clearCompleted()\n }\n }\n }\n }\n\n}\n\nfun main(args: Array) {\n Komponent.create(document.body!!, TodoApp(), true)\n\n val el1 = document.create.div {\n div {\n div {\n id = \"id1\"\n span {\n +\"Test\"\n }\n }\n }\n }\n\n val el2 = document.create.div {\n div {\n id = \"id1\"\n span {\n +\"Test\"\n }\n input {\n name = \"bla\"\n }\n }\n }\n\n // println(\"equals ${DomDiffer.match(el1, el2)}\")\n\n console.log(\"OLD\", el1)\n console.log(\"NEW\", el2)\n\n DomDiffer.replaceDiff(el2, el1)\n\n console.log(\"OLD\", el1)\n console.log(\"NEW\", el2)\n}\n\n","@file:kotlin.jvm.JvmMultifileClass\n@file:kotlin.jvm.JvmName(\"MapsKt\")\n\npackage kotlin.collections\n\nprivate object EmptyMap : Map, Serializable {\n private const val serialVersionUID: Long = 8246714829545688274\n\n override fun equals(other: Any?): Boolean = other is Map<*,*> && other.isEmpty()\n override fun hashCode(): Int = 0\n override fun toString(): String = \"{}\"\n\n override val size: Int get() = 0\n override fun isEmpty(): Boolean = true\n\n override fun containsKey(key: Any?): Boolean = false\n override fun containsValue(value: Nothing): Boolean = false\n override fun get(key: Any?): Nothing? = null\n override val entries: Set> get() = EmptySet\n override val keys: Set get() = EmptySet\n override val values: Collection get() = EmptyList\n\n private fun readResolve(): Any = EmptyMap\n}\n\n/**\n * Returns an empty read-only map of specified type.\n *\n * The returned map is serializable (JVM).\n * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap\n */\npublic fun emptyMap(): Map = @Suppress(\"UNCHECKED_CAST\") (EmptyMap as Map)\n\n/**\n * Returns a new read-only map with the specified contents, given as a list of pairs\n * where the first value is the key and the second is the value.\n *\n * If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.\n *\n * Entries of the map are iterated in the order they were specified.\n *\n * The returned map is serializable (JVM).\n *\n * @sample samples.collections.Maps.Instantiation.mapFromPairs\n */\npublic fun mapOf(vararg pairs: Pair): Map = if (pairs.size > 0) pairs.toMap(LinkedHashMap(mapCapacity(pairs.size))) else emptyMap()\n\n/**\n * Returns an empty read-only map.\n *\n * The returned map is serializable (JVM).\n * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap\n */\n@kotlin.internal.InlineOnly\npublic inline fun mapOf(): Map = emptyMap()\n\n/* Not available on platform: JS */\n\n\n\n\n\n\n\n\n\n\n/**\n * Returns an empty new [MutableMap].\n *\n * The returned map preserves the entry iteration order.\n * @sample samples.collections.Maps.Instantiation.emptyMutableMap\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline fun mutableMapOf(): MutableMap = LinkedHashMap()\n\n/**\n * Returns a new [MutableMap] with the specified contents, given as a list of pairs\n * where the first component is the key and the second is the value.\n *\n * If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.\n *\n * Entries of the map are iterated in the order they were specified.\n *\n * @sample samples.collections.Maps.Instantiation.mutableMapFromPairs\n * @sample samples.collections.Maps.Instantiation.emptyMutableMap\n */\npublic fun mutableMapOf(vararg pairs: Pair): MutableMap\n = LinkedHashMap(mapCapacity(pairs.size)).apply { putAll(pairs) }\n\n/**\n * Returns an empty new [HashMap].\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline fun hashMapOf(): HashMap = HashMap()\n\n/**\n * Returns a new [HashMap] with the specified contents, given as a list of pairs\n * where the first component is the key and the second is the value.\n *\n * @sample samples.collections.Maps.Instantiation.hashMapFromPairs\n */\npublic fun hashMapOf(vararg pairs: Pair): HashMap\n = HashMap(mapCapacity(pairs.size)).apply { putAll(pairs) }\n\n/**\n * Returns an empty new [LinkedHashMap].\n */\n@SinceKotlin(\"1.1\")\n@kotlin.internal.InlineOnly\npublic inline fun linkedMapOf(): LinkedHashMap = LinkedHashMap()\n\n/**\n * Returns a new [LinkedHashMap] with the specified contents, given as a list of pairs\n * where the first component is the key and the second is the value.\n *\n * If multiple pairs have the same key, the resulting map will contain the value from the last of those pairs.\n *\n * Entries of the map are iterated in the order they were specified.\n *\n * @sample samples.collections.Maps.Instantiation.linkedMapFromPairs\n */\npublic fun linkedMapOf(vararg pairs: Pair): LinkedHashMap\n = pairs.toMap(LinkedHashMap(mapCapacity(pairs.size)))\n\n/**\n * Calculate the initial capacity of a map, based on Guava's com.google.common.collect.Maps approach. This is equivalent\n * to the Collection constructor for HashSet, (c.size()/.75f) + 1, but provides further optimisations for very small or\n * very large sizes, allows support non-collection classes, and provides consistency for all map based class construction.\n */\n@PublishedApi\ninternal fun mapCapacity(expectedSize: Int): Int {\n if (expectedSize < 3) {\n return expectedSize + 1\n }\n if (expectedSize < INT_MAX_POWER_OF_TWO) {\n return expectedSize + expectedSize / 3\n }\n return Int.MAX_VALUE // any large value\n}\n\nprivate const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1\n\n/** Returns `true` if this map is not empty. */\n@kotlin.internal.InlineOnly\npublic inline fun Map.isNotEmpty(): Boolean = !isEmpty()\n\n/**\n * Returns the [Map] if its not `null`, or the empty [Map] otherwise.\n */\n@kotlin.internal.InlineOnly\npublic inline fun Map?.orEmpty() : Map = this ?: emptyMap()\n\n/**\n * Checks if the map contains the given key.\n *\n * This method allows to use the `x in map` syntax for checking whether an object is contained in the map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.contains(key: K) : Boolean = containsKey(key)\n\n/**\n * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map.\n */\n@kotlin.internal.InlineOnly\npublic inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.get(key: K): V?\n = @Suppress(\"UNCHECKED_CAST\") (this as Map