Add input listeners

This commit is contained in:
Alexander Nozik 2023-12-06 23:01:22 +03:00
parent bce61c0fb0
commit 05b87857f4
6 changed files with 31 additions and 18 deletions

View File

@ -13,6 +13,7 @@ import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionClient
import space.kscience.visionforge.react.render
import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
@ -26,9 +27,9 @@ public class ThreeWithControlsPlugin : AbstractPlugin(), ElementVisionRenderer {
override fun rateVision(vision: Vision): Int =
if (vision is Solid) ElementVisionRenderer.DEFAULT_RATING * 2 else ElementVisionRenderer.ZERO_RATING
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
if (meta["controls.enabled"].boolean == false) {
three.render(element, name, vision, meta)
three.render(element, client, name, vision, meta)
} else {
space.kscience.visionforge.react.createRoot(element).render {
child(ThreeCanvasWithControls) {

View File

@ -1,8 +1,11 @@
package space.kscience.visionforge
import kotlinx.browser.document
import kotlinx.coroutines.launch
import kotlinx.dom.clear
import kotlinx.html.InputType
import kotlinx.html.div
import kotlinx.html.dom.append
import kotlinx.html.js.input
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLFormElement
@ -13,6 +16,7 @@ import org.w3c.xhr.FormData
import space.kscience.dataforge.context.debug
import space.kscience.dataforge.context.logger
import space.kscience.dataforge.meta.*
import space.kscience.dataforge.names.Name
import space.kscience.visionforge.html.*
/**
@ -27,6 +31,12 @@ private fun HTMLElement.subscribeToVision(vision: VisionOfHtml) {
}
private fun VisionClient.sendInputEvent(name: Name, value: Value?) {
context.launch {
sendEvent(name, VisionValueChangeEvent(value))
}
}
/**
* Subscribes the HTML input element to a given vision.
*
@ -44,6 +54,10 @@ internal val htmlVisionRenderer: ElementVisionRenderer =
div {}.also { div ->
div.subscribeToVision(vision)
vision.useProperty(VisionOfPlainHtml::content) {
div.clear()
div.append {
}
div.textContent = it
}
}
@ -57,7 +71,7 @@ internal val inputVisionRenderer: ElementVisionRenderer =
type = InputType.text
}.also { htmlInputElement ->
val onEvent: (Event) -> Unit = {
client.sendEvent(name, VisionValueChangeEvent(htmlInputElement.value.asValue()))
client.sendInputEvent(name, htmlInputElement.value.asValue())
}
@ -81,7 +95,7 @@ internal val checkboxVisionRenderer: ElementVisionRenderer =
type = InputType.checkBox
}.also { htmlInputElement ->
val onEvent: (Event) -> Unit = {
client.sendEvent(name, VisionValueChangeEvent(htmlInputElement.checked.asValue()))
client.sendInputEvent(name, htmlInputElement.value.asValue())
}
@ -105,7 +119,7 @@ internal val textVisionRenderer: ElementVisionRenderer =
type = InputType.text
}.also { htmlInputElement ->
val onEvent: (Event) -> Unit = {
client.sendEvent(name, VisionValueChangeEvent(htmlInputElement.value.asValue()))
client.sendInputEvent(name, htmlInputElement.value.asValue())
}
@ -131,7 +145,7 @@ internal val numberVisionRenderer: ElementVisionRenderer =
val onEvent: (Event) -> Unit = {
htmlInputElement.value.toDoubleOrNull()?.let {
client.sendEvent(name, VisionValueChangeEvent(it.asValue()))
client.sendInputEvent(name, htmlInputElement.value.asValue())
}
}
@ -159,7 +173,7 @@ internal val rangeVisionRenderer: ElementVisionRenderer =
val onEvent: (Event) -> Unit = {
htmlInputElement.value.toDoubleOrNull()?.let {
client.sendEvent(name, VisionValueChangeEvent(it.asValue()))
client.sendInputEvent(name, htmlInputElement.value.asValue())
}
}
@ -200,7 +214,7 @@ internal fun FormData.toMeta(): Meta {
}
internal val formVisionRenderer: ElementVisionRenderer =
ElementVisionRenderer<VisionOfHtmlForm> { _, vision, _ ->
ElementVisionRenderer<VisionOfHtmlForm> { name, client, vision, _ ->
val form = document.getElementById(vision.formId) as? HTMLFormElement
?: error("An element with id = '${vision.formId} is not a form")
@ -220,7 +234,7 @@ internal val formVisionRenderer: ElementVisionRenderer =
form.onsubmit = { event ->
event.preventDefault()
val formData = FormData(form).toMeta()
vision.values = formData
client.sendMetaEvent(name, formData)
console.info("Sent: ${formData.toMap()}")
false
}

View File

@ -27,7 +27,7 @@ public actual class MarkupPlugin : VisionPlugin(), ElementVisionRenderer {
else -> ElementVisionRenderer.ZERO_RATING
}
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
require(vision is VisionOfMarkup) { "The vision is not a markup vision" }
val div = document.createElement("div")
val flavour = when (vision.format) {

View File

@ -10,10 +10,7 @@ import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName
import space.kscience.plotly.PlotlyConfig
import space.kscience.plotly.plot
import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.JsVisionClient
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionPlugin
import space.kscience.visionforge.*
public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer {
public val visionClient: JsVisionClient by require(JsVisionClient)
@ -27,7 +24,7 @@ public actual class PlotlyPlugin : VisionPlugin(), ElementVisionRenderer {
else -> ElementVisionRenderer.ZERO_RATING
}
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
val plot = (vision as? VisionOfPlotly)?.plot ?: error("VisionOfPlotly expected but ${vision::class} found")
val config = PlotlyConfig.read(meta)
element.plot(config, plot)

View File

@ -14,6 +14,7 @@ import space.kscience.dataforge.names.asName
import space.kscience.visionforge.ElementVisionRenderer
import space.kscience.visionforge.JsVisionClient
import space.kscience.visionforge.Vision
import space.kscience.visionforge.VisionClient
import tabulator.Tabulator
import tabulator.TabulatorFull
@ -34,7 +35,7 @@ public class TableVisionJsPlugin : AbstractPlugin(), ElementVisionRenderer {
else -> ElementVisionRenderer.ZERO_RATING
}
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
val table: VisionOfTable = (vision as? VisionOfTable)
?: error("VisionOfTable expected but ${vision::class} found")

View File

@ -150,7 +150,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
render(vision)
}
override fun render(element: Element, name: Name, vision: Vision, meta: Meta) {
override fun render(element: Element, client: VisionClient, name: Name, vision: Vision, meta: Meta) {
renderSolid(
element,
vision as? Solid ?: error("Solid expected but ${vision::class} found"),