Update readme
This commit is contained in:
379
readme.md
379
readme.md
@@ -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)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user