Update readme

This commit is contained in:
2019-11-15 19:13:45 +01:00
parent 928c6a6c03
commit 8f7b03b5b8
2 changed files with 211 additions and 171 deletions

379
readme.md
View File

@@ -16,9 +16,29 @@ Complete source:
```kotlin ```kotlin
package nl.astraeus.komp.todo package nl.astraeus.komp.todo
import kotlinx.html.* import kotlinx.html.HtmlBlockTag
import kotlinx.html.js.* import kotlinx.html.InputType
import kotlinx.html.TagConsumer
import kotlinx.html.a
import kotlinx.html.button
import kotlinx.html.classes
import kotlinx.html.div
import kotlinx.html.footer
import kotlinx.html.h1
import kotlinx.html.header
import kotlinx.html.id
import kotlinx.html.input
import kotlinx.html.js.onClickFunction
import kotlinx.html.js.onDoubleClickFunction
import kotlinx.html.js.onKeyPressFunction
import kotlinx.html.label
import kotlinx.html.li
import kotlinx.html.section
import kotlinx.html.span
import kotlinx.html.strong
import kotlinx.html.ul
import nl.astraeus.komp.Komponent import nl.astraeus.komp.Komponent
import nl.astraeus.komp.include
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
@@ -27,206 +47,227 @@ import kotlin.browser.document
import kotlin.js.Date import kotlin.js.Date
/** /**
* https://github.com/tastejs/todomvc/ * see: https://github.com/tastejs/todomvc/
*/ */
class Todo( class Todo(
val dataId: String, val dataId: String,
var title: String, var title: String,
var completed: Boolean = false, var completed: Boolean = false,
var editing: Boolean = false var editing: Boolean = false
) )
enum class Selection(val title: String) { enum class Selection(val title: String) {
ALL("All"), ALL("All"),
ACTIVE("Active"), ACTIVE("Active"),
COMPLETED("Completed") COMPLETED("Completed")
} }
class TodoApp: Komponent() { fun HtmlBlockTag.todo(app: TodoApp, todo: Todo) {
val todoList: MutableList<Todo> = ArrayList() this.include(TodoKomponent(app, todo))
var selected: Selection = Selection.ALL }
fun addTodo(e: Event) { class TodoKomponent(
val target = e.target val app: TodoApp,
val todo: Todo
) : Komponent() {
if (target is HTMLInputElement) { override fun render(consumer: TagConsumer<HTMLElement>) = consumer.li {
todoList.add(Todo("${Date().getTime()}", target.value)) if (todo.editing) {
classes += "editing"
refresh() input(classes = "edit") {
value = todo.title
onKeyPressFunction = { e ->
val target = e.target
if (target is HTMLInputElement && e is KeyboardEvent && e.keyCode == 13 && target.value.isNotBlank()) {
app.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 = {
app.todoClicked(todo)
}
}
label(classes = "todo-content") {
+todo.title
onDoubleClickFunction = {
app.setEditing(todo)
}
}
button(classes = "destroy") {
onClickFunction = {
app.destroyTodo(todo)
}
}
}
}
}
}
class TodoApp : Komponent() {
val todoList: MutableList<Todo> = 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 editTodo(e: Event, todo: Todo) { }
val target = e.target
if (target is HTMLInputElement) { fun destroyTodo(todo: Todo) {
todo.title = target.value todoList.remove(todo)
todo.editing = false
refresh() refresh()
} }
} fun selectSelection(selection: Selection) {
selected = selection
fun destroyTodo(todo: Todo) { refresh()
}
fun clearCompleted() {
for (todo in ArrayList(todoList)) {
if (todo.completed) {
todoList.remove(todo) todoList.remove(todo)
}
refresh()
} }
fun selectSelection(selection: Selection) { refresh()
selected = selection }
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
} }
fun clearCompleted() { refresh()
for (todo in ArrayList(todoList)) { }
if (todo.completed) {
todoList.remove(todo) override fun refresh() {
} super.refresh()
val inputBox = document.getElementById("todo_input")
if (inputBox is HTMLInputElement) {
inputBox.focus()
}
}
override fun render(consumer: TagConsumer<HTMLElement>) = 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 ->
val target = e.target
if (target is HTMLInputElement && e is KeyboardEvent && e.keyCode == 13 && target.value.isNotBlank()) {
addTodo(e)
target.value = ""
target.defaultValue = ""
}
} }
}
refresh()
} }
fun todoClicked(todo: Todo) { section(classes = "main") {
todo.completed = !todo.completed input(classes = "toggle-all") {
type = InputType.checkBox
refresh() }
} label {
htmlFor = "toggle-all"
fun getItemsLeft(): Int { +"Mark all as complete"
var result = 0 }
ul(classes = "todo-list") {
for (todo in todoList) { for (todo in todoList) {
if (!todo.completed) { if (selected == Selection.ALL ||
result++ (todo.completed && selected == Selection.COMPLETED) ||
} (!todo.completed && selected == Selection.ACTIVE)) {
todo(this@TodoApp, todo)
}
} }
return result }
} }
fun setEditing(editTodo: Todo) { footer(classes = "footer") {
for (todo in todoList) { span(classes = "todo-count") {
todo.editing = todo == editTodo strong { +"${getItemsLeft()}" }
} +" item left"
}
refresh() ul(classes = "filters") {
} for (selection in Selection.values()) {
li {
override fun refresh() { a {
super.refresh() if (selection == selected) {
classes += "selected"
val inputBox = document.getElementById("todo_input") }
href = "#"
if (inputBox is HTMLInputElement) { +selection.title
inputBox.focus() onClickFunction = {
} selectSelection(selection)
} }
}
override fun render(consumer: TagConsumer<HTMLElement>) = 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()
}
}
} }
}
button(classes = "clear-completed") {
+"Clear completed"
onClickFunction = {
clearCompleted()
}
}
} }
}
} }
fun main(args: Array<String>) { fun main() {
Komponent.create(document.body!!, TodoApp(), true) Komponent.create(document.body!!, TodoApp(), true)
} }
``` ```

View File

@@ -21,7 +21,6 @@ import kotlinx.html.section
import kotlinx.html.span import kotlinx.html.span
import kotlinx.html.strong import kotlinx.html.strong
import kotlinx.html.ul import kotlinx.html.ul
import kotlinx.html.video
import nl.astraeus.komp.Komponent import nl.astraeus.komp.Komponent
import nl.astraeus.komp.include import nl.astraeus.komp.include
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
@@ -32,7 +31,7 @@ import kotlin.browser.document
import kotlin.js.Date import kotlin.js.Date
/** /**
* https://github.com/tastejs/todomvc/ * see: https://github.com/tastejs/todomvc/
*/ */
class Todo( class Todo(