diff --git a/.idea/libraries/Gradle__nl_astraeus_komp_0_0_4_SNAPSHOT.xml b/.idea/libraries/Gradle__nl_astraeus_komp_0_0_4_SNAPSHOT.xml
deleted file mode 100644
index d79a802..0000000
--- a/.idea/libraries/Gradle__nl_astraeus_komp_0_0_4_SNAPSHOT.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Gradle__nl_astraeus_komp_0_0_5_SNAPSHOT.xml b/.idea/libraries/Gradle__nl_astraeus_komp_0_0_5_SNAPSHOT.xml
new file mode 100644
index 0000000..cceeaf9
--- /dev/null
+++ b/.idea/libraries/Gradle__nl_astraeus_komp_0_0_5_SNAPSHOT.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_1_0.xml b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_1_0.xml
index ec3824b..3810470 100644
--- a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_1_0.xml
+++ b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_common_1_1_0.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_js_1_1_4_eap_11.xml b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_js_1_1_4.xml
similarity index 50%
rename from .idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_js_1_1_4_eap_11.xml
rename to .idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_js_1_1_4.xml
index 95b60ea..1b8b422 100644
--- a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_js_1_1_4_eap_11.xml
+++ b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_js_1_1_4.xml
@@ -1,11 +1,11 @@
-
+
-
+
-
+
\ No newline at end of file
diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_common_0_6_2.xml b/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_common_0_6_2.xml
index bf3b635..835e744 100644
--- a/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_common_0_6_2.xml
+++ b/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_common_0_6_2.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_js_0_6_2.xml b/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_js_0_6_2.xml
index 68648b4..902474d 100644
--- a/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_js_0_6_2.xml
+++ b/.idea/libraries/Gradle__org_jetbrains_kotlinx_kotlinx_html_js_0_6_2.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/.idea/modules/komp-todo_main.iml b/.idea/modules/komp-todo_main.iml
index 7852526..75729da 100644
--- a/.idea/modules/komp-todo_main.iml
+++ b/.idea/modules/komp-todo_main.iml
@@ -10,6 +10,7 @@
+
@@ -21,11 +22,7 @@
-
+
@@ -42,8 +39,8 @@
-
-
+
+
diff --git a/.idea/modules/komp-todo_test.iml b/.idea/modules/komp-todo_test.iml
index 1de8514..a248cf0 100644
--- a/.idea/modules/komp-todo_test.iml
+++ b/.idea/modules/komp-todo_test.iml
@@ -7,6 +7,7 @@
+
@@ -18,11 +19,6 @@
-
-
-
-
-
@@ -39,8 +35,8 @@
-
-
+
+
diff --git a/build.gradle b/build.gradle
index a4e35cb..b1e5a87 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,7 +2,7 @@ group 'nl.astraeus'
version '0.0.1-SNAPSHOT'
buildscript {
- ext.kotlin_version = '1.1.4-eap-11'
+ ext.kotlin_version = '1.1.4'
repositories {
maven {
@@ -21,7 +21,7 @@ buildscript {
allprojects {
ext {
- kotlin_version = '1.1.4-eap-11'
+ kotlin_version = '1.1.4'
}
}
@@ -37,7 +37,7 @@ repositories {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
- compile "nl.astraeus:komp:0.0.4-SNAPSHOT"
+ compile "nl.astraeus:komp:0.0.5-SNAPSHOT"
}
compileKotlin2Js {
diff --git a/readme.md b/readme.md
index e094e0f..a3886e1 100644
--- a/readme.md
+++ b/readme.md
@@ -1 +1,230 @@
-https://github.com/tastejs/todomvc/
\ No newline at end of file
+An example on how to build a single page app with Kotlin (javascript) using static html builders.
+
+Runing example: [komp-todo](http://todo.astraeus.nl/)
+
+Compare it with other js frameworks: [https://github.com/tastejs/todomvc/](https://github.com/tastejs/todomvc/)
+
+Dependencies:
+
+* [kotlinx-html-js](https://github.com/Kotlin/kotlinx.html)
+* [komponent](https://github.com/rnentjes/komponent)
+
+Complete source:
+
+```kotlin
+package nl.astraeus.komp.todo
+
+import kotlinx.html.*
+import kotlinx.html.js.*
+import nl.astraeus.komp.Komponent
+import org.w3c.dom.HTMLElement
+import org.w3c.dom.HTMLInputElement
+import org.w3c.dom.events.Event
+import org.w3c.dom.events.KeyboardEvent
+import kotlin.browser.document
+import kotlin.js.Date
+
+/**
+ * https://github.com/tastejs/todomvc/
+ */
+
+class Todo(
+ val dataId: String,
+ var title: String,
+ var completed: Boolean = false,
+ var editing: Boolean = false
+)
+
+enum class Selection(val title: String) {
+ ALL("All"),
+ ACTIVE("Active"),
+ COMPLETED("Completed")
+}
+
+class TodoApp: Komponent() {
+ val todoList: MutableList = ArrayList()
+ var selected: Selection = Selection.ALL
+
+ fun addTodo(e: Event) {
+ val target = e.target
+
+ if (target is HTMLInputElement) {
+ todoList.add(Todo("${Date().getTime()}", target.value))
+
+ refresh()
+ }
+ }
+
+ fun editTodo(e: Event, todo: Todo) {
+ val target = e.target
+
+ if (target is HTMLInputElement) {
+ todo.title = target.value
+ todo.editing = false
+
+ refresh()
+ }
+
+ }
+
+ fun destroyTodo(todo: Todo) {
+ todoList.remove(todo)
+
+ refresh()
+ }
+
+ fun selectSelection(selection: Selection) {
+ selected = selection
+
+ refresh()
+ }
+
+ fun clearCompleted() {
+ for (todo in ArrayList(todoList)) {
+ if (todo.completed) {
+ todoList.remove(todo)
+ }
+ }
+
+ refresh()
+ }
+
+ fun todoClicked(todo: Todo) {
+ todo.completed = !todo.completed
+
+ refresh()
+ }
+
+ fun getItemsLeft(): Int {
+ var result = 0
+ for (todo in todoList) {
+ if (!todo.completed) {
+ result++
+ }
+ }
+ return result
+ }
+
+ fun setEditing(editTodo: Todo) {
+ for (todo in todoList) {
+ todo.editing = todo == editTodo
+ }
+
+ refresh()
+ }
+
+ override fun refresh() {
+ super.refresh()
+
+ val inputBox = document.getElementById("todo_input")
+
+ if (inputBox is HTMLInputElement) {
+ inputBox.focus()
+ }
+ }
+
+ override fun render(consumer: TagConsumer) = consumer.section(classes = "todoapp") {
+ header(classes = "header") {
+ h1 { + "todos" }
+ input(classes = "new-todo") {
+ id = "todo_input"
+ placeholder = "What needs to be done?"
+ autoFocus = true
+ onKeyPressFunction = { e ->
+ if (e is KeyboardEvent && e.keyCode == 13) {
+ addTodo(e)
+ }
+ }
+ }
+ }
+
+ section(classes = "main") {
+ input(classes = "toggle-all") {
+ type = InputType.checkBox
+ }
+ label {
+ for_ = "toggle-all"
+ + "Mark all as complete"
+ }
+ ul(classes = "todo-list") {
+ for (todo in todoList) {
+ if (selected == Selection.ALL ||
+ (todo.completed && selected == Selection.COMPLETED) ||
+ (!todo.completed && selected == Selection.ACTIVE)) {
+ li {
+ if (todo.editing) {
+ classes += "editing"
+ input(classes = "edit") {
+ value = todo.title
+ onKeyPressFunction = { e ->
+ if (e is KeyboardEvent && e.keyCode == 13) {
+ editTodo(e, todo)
+ }
+ }
+ }
+ } else {
+ if (todo.completed) {
+ classes += "completed"
+ }
+ attributes["data-id"] = todo.dataId
+ div(classes = "view") {
+ input(classes = "toggle") {
+ type = InputType.checkBox
+ checked = todo.completed
+ onClickFunction = {
+ todoClicked(todo)
+ }
+ }
+ label(classes = "todo-content") {
+ +todo.title
+
+ onDoubleClickFunction = {
+ setEditing(todo)
+ }
+ }
+ button(classes = "destroy") {
+ onClickFunction = {
+ destroyTodo(todo)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ footer(classes = "footer") {
+ span(classes = "todo-count") {
+ strong { + "${getItemsLeft()}" }
+ + " item left"
+ }
+ ul(classes = "filters") {
+ for (selection in Selection.values())
+ li {
+ a {
+ if (selection == selected) { classes += "selected" }
+ href = "#"
+ + selection.title
+ onClickFunction = {
+ selectSelection(selection)
+ }
+ }
+ }
+ }
+ button(classes = "clear-completed") {
+ + "Clear completed"
+ onClickFunction = {
+ clearCompleted()
+ }
+ }
+ }
+ }
+
+}
+
+fun main(args: Array) {
+ Komponent.create(document.body!!, TodoApp(), true)
+}
+```
\ No newline at end of file
diff --git a/web/index.html b/web/index.html
index b096035..84980ea 100644
--- a/web/index.html
+++ b/web/index.html
@@ -14,4 +14,4 @@