@@ -5,14 +5,14 @@ use web_sys::{js_sys::Function, window, HtmlElement};
5
5
/// Provides utilities for binding Plotly.js click events to Rust closures
6
6
/// via `wasm-bindgen`.
7
7
///
8
- /// This module defines a `PlotlyDiv` foreign type for the Plotly `<div>` element,
9
- /// a high-level `bind_click` function to wire up Rust callbacks, and
8
+ /// This module defines a `PlotlyDiv` foreign type for the Plotly `<div>`
9
+ /// element, a high-level `bind_click` function to wire up Rust callbacks, and
10
10
/// the `ClickPoint`/`ClickEvent` data structures to deserialize event payloads.
11
-
12
11
#[ wasm_bindgen]
13
12
extern "C" {
14
13
15
- /// A wrapper around the JavaScript `HTMLElement` representing a Plotly `<div>`.
14
+ /// A wrapper around the JavaScript `HTMLElement` representing a Plotly
15
+ /// `<div>`.
16
16
///
17
17
/// This type extends `web_sys::HtmlElement` and exposes Plotly’s
18
18
/// `.on(eventName, callback)` method for attaching event listeners.
@@ -37,17 +37,18 @@ extern "C" {
37
37
/// Bind a Rust callback to the Plotly `plotly_click` event on a given `<div>`.
38
38
///
39
39
/// # Type Parameters
40
- /// - `F`: A `'static + FnMut(ClickEvent)` closure type to handle the click data.
40
+ /// - `F`: A `'static + FnMut(ClickEvent)` closure type to handle the click
41
+ /// data.
41
42
///
42
43
/// # Parameters
43
44
/// - `div_id`: The DOM `id` attribute of the Plotly `<div>`.
44
45
/// - `cb`: A mutable Rust closure that will be called with a `ClickEvent`.
45
46
///
46
47
/// # Details
47
- /// 1. Looks up the element by `div_id`, converts it to `PlotlyDiv`.
48
- /// 2. Wraps a `Closure<dyn FnMut(JsValue)>` that deserializes the JS event
49
- /// into our `ClickEvent` type via `serde_wasm_bindgen`.
50
- /// 3. Calls `plot_div.on("plotly_click", …)` to register the listener.
48
+ /// 1. Looks up the element by `div_id`, converts it to `PlotlyDiv`.
49
+ /// 2. Wraps a `Closure<dyn FnMut(JsValue)>` that deserializes the JS event into
50
+ /// our `ClickEvent` type via `serde_wasm_bindgen`.
51
+ /// 3. Calls `plot_div.on("plotly_click", …)` to register the listener.
51
52
/// 4. Forgets the closure so it lives for the lifetime of the page.
52
53
///
53
54
/// # Example
@@ -56,43 +57,41 @@ extern "C" {
56
57
/// web_sys::console::log_1(&format!("{:?}", evt).into());
57
58
/// });
58
59
/// ```
59
-
60
-
61
60
pub fn bind_click < F > ( div_id : & str , mut cb : F )
62
- where
63
- F : ' static + FnMut ( ClickEvent )
61
+ where
62
+ F : ' static + FnMut ( ClickEvent ) ,
64
63
{
65
-
66
- let plot_div: PlotlyDiv = window ( ) . unwrap ( )
67
- . document ( ) . unwrap ( )
68
- . get_element_by_id ( div_id) . unwrap ( )
64
+ let plot_div: PlotlyDiv = window ( )
65
+ . unwrap ( )
66
+ . document ( )
67
+ . unwrap ( )
68
+ . get_element_by_id ( div_id)
69
+ . unwrap ( )
69
70
. unchecked_into ( ) ;
70
71
let closure = Closure :: wrap ( Box :: new ( move |event : JsValue | {
71
- let event: ClickEvent = serde_wasm_bindgen :: from_value ( event )
72
- . expect ( "\n Couldn't serialize the event \n " ) ;
72
+ let event: ClickEvent =
73
+ serde_wasm_bindgen :: from_value ( event ) . expect ( "\n Couldn't serialize the event \n " ) ;
73
74
cb ( event) ;
74
75
} ) as Box < dyn FnMut ( JsValue ) > ) ;
75
- plot_div. on ( "plotly_click" , & closure. as_ref ( ) . unchecked_ref ( ) ) ;
76
+ plot_div. on ( "plotly_click" , closure. as_ref ( ) . unchecked_ref ( ) ) ;
76
77
closure. forget ( ) ;
77
78
}
78
79
79
-
80
80
/// Represents a single point from a Plotly click event.
81
81
///
82
82
/// Fields mirror Plotly’s `event.points[i]` properties, all optional
83
83
/// where appropriate:
84
84
///
85
85
/// - `curve_number`: The zero-based index of the trace that was clicked.
86
- /// - `point_numbers`: An optional list of indices if multiple points were selected.
86
+ /// - `point_numbers`: An optional list of indices if multiple points were
87
+ /// selected.
87
88
/// - `point_number`: The index of the specific point clicked (if singular).
88
89
/// - `x`, `y`, `z`: Optional numeric coordinates in data space.
89
90
/// - `lat`, `lon`: Optional geographic coordinates (for map plots).
90
91
///
91
92
/// # Serialization
92
93
/// Uses `serde` with `camelCase` field names to match Plotly’s JS API.
93
-
94
-
95
- #[ derive( Debug , Deserialize , Serialize , Default ) ]
94
+ #[ derive( Debug , Deserialize , Serialize , Default ) ]
96
95
#[ serde( rename_all = "camelCase" ) ]
97
96
pub struct ClickPoint {
98
97
pub curve_number : usize ,
@@ -102,41 +101,38 @@ pub struct ClickPoint {
102
101
pub y : Option < f64 > ,
103
102
pub z : Option < f64 > ,
104
103
pub lat : Option < f64 > ,
105
- pub lon : Option < f64 >
104
+ pub lon : Option < f64 > ,
106
105
}
107
106
108
-
109
107
/// Provide a default single-point vector for `ClickEvent::points`.
110
108
///
111
109
/// Returns `vec![ClickPoint::default()]` so deserialization always yields
112
110
/// at least one element rather than an empty vector.
113
-
114
- fn default_click_event ( ) -> Vec < ClickPoint > { vec ! [ ClickPoint :: default ( ) ] }
115
-
111
+ fn default_click_event ( ) -> Vec < ClickPoint > {
112
+ vec ! [ ClickPoint :: default ( ) ]
113
+ }
116
114
117
115
/// The top-level payload for a Plotly click event.
118
116
///
119
- /// - `points`: A `Vec<ClickPoint>` containing all clicked points.
120
- /// Defaults to the result of `default_click_event` to ensure
121
- /// `points` is non-empty even if Plotly sends no data.
117
+ /// - `points`: A `Vec<ClickPoint>` containing all clicked points. Defaults to
118
+ /// the result of `default_click_event` to ensure `points` is non-empty even
119
+ /// if Plotly sends no data.
122
120
///
123
121
/// # Serialization
124
122
/// Uses `serde` with `camelCase` names and a custom default so you can
125
123
/// call `event.points` without worrying about missing values.
126
-
127
- #[ derive( Debug , Deserialize , Serialize ) ]
128
- #[ serde( rename_all="camelCase" , default ) ]
124
+ #[ derive( Debug , Deserialize , Serialize ) ]
125
+ #[ serde( rename_all = "camelCase" , default ) ]
129
126
pub struct ClickEvent {
130
- #[ serde( default = "default_click_event" ) ]
131
- pub points : Vec < ClickPoint >
127
+ #[ serde( default = "default_click_event" ) ]
128
+ pub points : Vec < ClickPoint > ,
132
129
}
133
130
134
131
/// A `Default` implementation yielding an empty `points` vector.
135
132
///
136
133
/// Useful when you need a zero-event placeholder (e.g., initial state).
137
-
138
134
impl Default for ClickEvent {
139
135
fn default ( ) -> Self {
140
136
ClickEvent { points : vec ! [ ] }
141
137
}
142
- }
138
+ }
0 commit comments