use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
use web_sys::{js_sys::Function, HtmlElement};
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(extends= HtmlElement, js_name=HTMLElement)]
type PlotlyDiv;
#[wasm_bindgen(method,structural,js_name=on)]
fn on(this: &PlotlyDiv, event: &str, cb: &Function);
}
pub fn bind_click<F>(div_id: &str, mut cb: F)
where
F: 'static + FnMut(ClickEvent),
{
let closure = Closure::wrap(Box::new(move |event: JsValue| {
let event: ClickEvent =
serde_wasm_bindgen::from_value(event).expect("Could not serialize the event");
cb(event);
}) as Box<dyn FnMut(JsValue)>);
let plot_div: PlotlyDiv = get_div(div_id).expect("Could not get Div element by Id");
plot_div.on("plotly_click", closure.as_ref().unchecked_ref());
closure.forget();
}
fn get_div(tag: &str) -> Option<PlotlyDiv> {
web_sys::window()?
.document()?
.get_element_by_id(tag)?
.dyn_into()
.ok()
}
#[derive(Debug, Deserialize, Serialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ClickPoint {
pub curve_number: usize,
pub point_numbers: Option<Vec<usize>>,
pub point_number: Option<usize>,
pub x: Option<f64>,
pub y: Option<f64>,
pub z: Option<f64>,
pub lat: Option<f64>,
pub lon: Option<f64>,
}
fn default_click_event() -> Vec<ClickPoint> {
vec![ClickPoint::default()]
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", default)]
pub struct ClickEvent {
#[serde(default = "default_click_event")]
pub points: Vec<ClickPoint>,
}
impl Default for ClickEvent {
fn default() -> Self {
ClickEvent { points: vec![] }
}
}