Skip to content

Commit

Permalink
Add event support to JS
Browse files Browse the repository at this point in the history
  • Loading branch information
altavir committed Jun 25, 2023
1 parent 1e2199f commit 389f357
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.w3c.dom.events.Event
import space.kscience.dataforge.meta.MetaSerializer
import space.kscience.dataforge.meta.toMutableMeta
import space.kscience.plotly.*
import space.kscience.plotly.events.PlotlyEventListenerType
import space.kscience.plotly.models.ScatterMode
import space.kscience.plotly.models.TraceType
import kotlin.random.Random
Expand Down Expand Up @@ -133,7 +134,9 @@ fun main(): Unit = withCanvas {
val serialized = plot.toJsonString()
console.log(serialized)
val deserialized = Plot(Json.decodeFromString(MetaSerializer, serialized).toMutableMeta())
plotDiv(plot = deserialized)
plotDiv(plot = deserialized).on(PlotlyEventListenerType.CLICK){
console.info(it.toString())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
package space.kscience.plotly.events

import space.kscience.dataforge.meta.*
import space.kscience.plotly.list
import space.kscience.plotly.models.Trace
import kotlinx.serialization.json.JsonElement
import space.kscience.dataforge.meta.Value

public enum class PlotlyEventListenerType(public val typeName: String){
public enum class PlotlyEventListenerType(public val eventType: String){
CLICK("plotly_click"),
HOVER("plotly_hover"),
UNHOVER("plotly_unhover"),
SELECTING("plotly_selecting"),
SELECTED("plotly_selected")
}

public class PlotlyEventPoint : Scheme() {
public val curveNumber: Int by int(1)
public val pointNumber: Int? by int()
public val x: Value? by value()
public val y: Value? by value()
public data class PlotlyEventPoint(
public val curveNumber: Int,
public val data: JsonElement,
public val pointNumber: Int? = null,
public val x: Value? = null,
public val y: Value? = null,
//
// public var data: Trace by spec(Trace)
// public var fullData: Trace by spec(Trace)
)

public val data: Trace by spec(Trace)
public val fullData: Trace by spec(Trace)

public companion object : SchemeSpec<PlotlyEventPoint>(::PlotlyEventPoint)
}


public class PlotlyEvent : Scheme() {
public val points: List<PlotlyEventPoint> by list(PlotlyEventPoint)

public companion object : SchemeSpec<PlotlyEvent>(::PlotlyEvent)
}
public data class PlotlyEvent(public val points: List<PlotlyEventPoint>)


Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ import kotlinx.html.TagConsumer
import kotlinx.html.div
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromDynamic
import kotlinx.serialization.json.encodeToDynamic
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement
import org.w3c.dom.events.Event
import space.kscience.dataforge.meta.DynamicMeta
import org.w3c.dom.events.MouseEvent
import space.kscience.dataforge.meta.MetaSerializer
import space.kscience.dataforge.meta.Scheme
import space.kscience.dataforge.meta.Value
import space.kscience.dataforge.names.asName
import space.kscience.dataforge.names.firstOrNull
import space.kscience.dataforge.names.startsWith
import space.kscience.plotly.events.PlotlyEvent
import space.kscience.plotly.events.PlotlyEventListenerType
import space.kscience.plotly.events.PlotlyEventPoint

@OptIn(ExperimentalSerializationApi::class)
private fun Scheme.toDynamic(): dynamic = Json.encodeToDynamic(MetaSerializer, meta)
Expand Down Expand Up @@ -87,10 +89,18 @@ public inline fun TagConsumer<HTMLElement>.plotDiv(
plotBuilder: Plot.() -> Unit,
): PlotlyElement = PlotlyElement(div("plotly-kt-plot").apply { plot(plotlyConfig, plotBuilder) })

public fun PlotlyElement.on(eventType: PlotlyEventListenerType, block: (PlotlyEvent) -> Unit) {
div.addEventListener(eventType.typeName, { event: Event->
val meta = DynamicMeta(event.asDynamic())
val plotlyEvent = PlotlyEvent.read(meta)
block(plotlyEvent)
})
@OptIn(ExperimentalSerializationApi::class)
public fun PlotlyElement.on(eventType: PlotlyEventListenerType, block: MouseEvent.(PlotlyEvent) -> Unit) {
div.asDynamic().on(eventType.eventType) { event: PlotMouseEvent ->
val eventData = PlotlyEvent(event.points.map {
PlotlyEventPoint(
curveNumber = it.curveNumber as Int,
pointNumber = it.pointNumber as? Int,
x = Value.of(it.x),
y = Value.of(it.y),
data = Json.decodeFromDynamic(it.data)
)
})
event.event.block(eventData)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package space.kscience.plotly

import org.w3c.dom.Element
import org.w3c.dom.events.MouseEvent
import kotlin.js.Promise

public external interface ToImgOpts {
Expand Down Expand Up @@ -47,3 +48,9 @@ public external object PlotlyJs {
public fun toImage(root: Element, opts: ToImgOpts): Promise<String>
public fun downloadImage(root: Element, opts: DownloadImgOpts): Promise<String>
}


public external interface PlotMouseEvent {
public val points : Array<dynamic>
public val event: MouseEvent
}

0 comments on commit 389f357

Please sign in to comment.