Skip to content

Instantly share code, notes, and snippets.

@sanity
Created February 4, 2017 19:14
Show Gist options
  • Save sanity/5c9cf631472238c1727610183789c50f to your computer and use it in GitHub Desktop.
Save sanity/5c9cf631472238c1727610183789c50f to your computer and use it in GitHub Desktop.
package com.github.sanity.kweb.demos.todo
import com.github.sanity.kweb.KWeb
import com.github.sanity.kweb.dom.element.creation.*
import com.github.sanity.kweb.dom.element.events.on
import com.github.sanity.kweb.dom.element.modification.addText
import com.github.sanity.kweb.dom.element.modification.delete
import kotlinx.coroutines.experimental.future.await
import kotlinx.coroutines.experimental.future.future
fun main(args: Array<String>) {
// Starts a web server listening on port 8091
KWeb(8091) {
doc.body.apply {
// Add a header element to the body, along with some simple instructions.
h1().addText("Simple KWeb demo - a to-do list")
p().addText("Edit the setText box below and click the button to add the item. Click an item to remove it.")
// If you're unfamiliar with the `apply` function, read this:
// http://beust.com/weblog/2015/10/30/exploring-the-kotlin-standard-library/
// We create a <ul> element, and then use apply() to add things to it
val ul = ul().apply {
// Add some initial items to the list
for (text in listOf("one", "two", "three")) {
// We define this below
newListItem(text)
}
}
// Next create an input element
val inputElement = input(type = InputType.text, size = 20)
// And a button to add a new item
val button = button()
button.addText("Add Item")
// Here we register a callback, the code block will be called when the
// user clicks this button.
button.on.click {
// This looks simple, but it is deceptively cool, and in more complex applications is the key to
// hiding the client/server divide in a fairly efficient matter. It uses Kotlin 1.1's new coroutines
// functionality, see https://github.com/Kotlin/kotlinx.coroutines
// We start an async block, which will allow us to use `await` within the block
future {
// This is where async comes in. inputElement.getValue() sends a message to the browser
// asking for the `value` of inputElement. This will take time so
// inputElement.getValue() actually returns a future. `await()` then uses coroutines
// to effectively wait until the future comes back, but crucially, without
// tying up a thread (which would getString very inefficient very quickly).
val newItemText = inputElement.getValue().await()
// And now we add the new item using our custom function
ul.newListItem(newItemText)
// And finally reset the value of the inputElement element.
inputElement.setValue("")
}
}
}
}
Thread.sleep(10000)
}
// Here we use an extension method which can be used on any <UL> element to add a list item which will
// delete itself when clicked.
fun ULElement.newListItem(text: String) {
li().apply {
addText(text)
on.click { event ->
delete() }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment