portal/src/jsMain/kotlin/de/westermann/kwebview/extensions.kt
2019-05-10 11:59:41 +02:00

143 lines
4.1 KiB
Kotlin

package de.westermann.kwebview
import de.westermann.kobserve.event.EventHandler
import org.w3c.dom.DOMRect
import org.w3c.dom.HTMLElement
import org.w3c.dom.events.Event
import org.w3c.dom.events.EventListener
import org.w3c.dom.events.MouseEvent
import org.w3c.xhr.FormData
import org.w3c.xhr.XMLHttpRequest
import kotlin.browser.document
import kotlin.browser.window
inline fun <reified V : HTMLElement> createHtmlView(tag: String? = null): V {
var tagName: String
if (tag != null) {
tagName = tag
} else {
tagName = V::class.js.name.toLowerCase().replace("html([a-z]*)element".toRegex(), "$1")
if (tagName.isBlank()) tagName = "div"
if (tagName == "anchor") tagName = "a"
}
return document.createElement(tagName) as V
}
fun String.toDashCase() = replace("([a-z])([A-Z])".toRegex(), "$1-$2").toLowerCase()
inline fun <reified T> EventHandler<T>.bind(element: HTMLElement, event: String) {
val listener = object : EventListener {
override fun handleEvent(event: Event) {
this@bind.emit(event as T)
}
}
var isAttached = false
val updateState = {
if (isEmpty() && isAttached) {
element.removeEventListener(event, listener)
isAttached = false
} else if (!isEmpty() && !isAttached) {
element.addEventListener(event, listener)
isAttached = true
}
}
onAttach = updateState
onDetach = updateState
updateState()
}
fun MouseEvent.toPoint(): Point = Point(clientX, clientY)
fun DOMRect.toDimension(): Dimension = Dimension(x, y, width, height)
fun Number.format(digits: Int): String = this.asDynamic().toFixed(digits)
external fun delete(p: dynamic): Boolean = definedExternally
fun delete(thing: dynamic, key: String) {
delete(thing[key])
}
/**
* Apply current dom changes and recalculate all sizes. Executes the given block afterwards.
*
* @param timeout Optionally set a timeout for this call. Defaults to 1.
* @param block Callback
*/
fun async(timeout: Int = 1, block: () -> Unit) {
if (timeout < 1) throw IllegalArgumentException("Timeout must be greater than 0!")
window.setTimeout(block, timeout)
}
fun interval(timeout: Int, block: () -> Unit): Int {
if (timeout < 1) throw IllegalArgumentException("Timeout must be greater than 0!")
return window.setInterval(block, timeout)
}
fun clearInterval(id: Int) {
window.clearInterval(id)
}
fun get(
url: String,
data: Map<String, String> = emptyMap(),
onError: (Int) -> Unit = {},
onSuccess: (String) -> Unit = {}
) {
val xhttp = XMLHttpRequest()
xhttp.onreadystatechange = {
if (xhttp.readyState == 4.toShort()) {
if (xhttp.status == 200.toShort() || xhttp.status == 304.toShort()) {
onSuccess(xhttp.responseText)
} else {
onError(xhttp.status.toInt())
}
}
}
xhttp.open("GET", url, true)
if (data.isNotEmpty()) {
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
val formData = FormData()
for ((key, value) in data) {
formData.append(key, value)
}
xhttp.send(formData)
} else {
xhttp.send()
}
}
fun post(
url: String,
data: Map<String, String> = emptyMap(),
onError: (Int) -> Unit = {},
onSuccess: (String) -> Unit = {}
) {
val xhttp = XMLHttpRequest()
xhttp.onreadystatechange = {
if (xhttp.readyState == 4.toShort()) {
console.log(xhttp.status)
if (xhttp.status == 200.toShort() || xhttp.status == 304.toShort()) {
onSuccess(xhttp.responseText)
} else {
onError(xhttp.status.toInt())
}
}
}
xhttp.open("POST", url, true)
if (data.isNotEmpty()) {
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
val formData = FormData()
for ((key, value) in data) {
formData.append(key, value)
}
xhttp.send(formData)
} else {
xhttp.send()
}
}