Added dynatos_util::ElementEventListener.

This commit is contained in:
Filipe Rodrigues 2024-02-04 00:41:04 +00:00
parent b17c9d8e41
commit e3d871a672
Signed by: zenithsiz
SSH Key Fingerprint: SHA256:Mb5ppb3Sh7IarBO/sBTXLHbYEOz37hJAlslLQPPAPaU
2 changed files with 86 additions and 0 deletions

View File

@ -0,0 +1,77 @@
//! Event listener
// Imports
use wasm_bindgen::{
closure::{Closure, IntoWasmClosure, WasmClosure},
JsCast,
};
/// Extension trait to define an event listener on an element with a closure
#[extend::ext_sized(name = ElementEventListener)]
pub impl web_sys::Element {
fn add_event_listener<E, F>(&self, f: F)
where
E: EventListener,
F: IntoWasmClosure<E::Closure> + 'static,
{
// Build the closure
let closure = Closure::<E::Closure>::new(f)
.into_js_value()
.dyn_into::<web_sys::js_sys::Function>()
.expect("Should be a valid function");
// Then add it
// TODO: Can this fail? On MDN, nothing seems to mention it can throw.
self.add_event_listener_with_callback(E::name(), &closure)
.expect("Unable to add event listener");
}
fn with_event_listener<E, F>(self, f: F) -> Self
where
E: EventListener,
F: IntoWasmClosure<E::Closure> + 'static,
{
self.add_event_listener::<E, F>(f);
self
}
}
/// Event listener
pub trait EventListener {
/// Closure type
type Closure: ?Sized + WasmClosure;
/// Returns the event name
fn name() -> &'static str;
}
/// Events
pub mod ev {
// Imports
use {super::EventListener, web_sys::PointerEvent};
macro define_events(
$(
$( #[ doc = $ev_doc:literal ] )*
$Event:ident($ArgTy:ty) = $name:literal;
)*
) {
$(
$( #[ doc = $ev_doc ] )*
pub struct $Event;
impl EventListener for $Event {
type Closure = dyn Fn($ArgTy);
fn name() -> &'static str {
$name
}
}
)*
}
define_events! {
/// `click` Event
Click(PointerEvent) = "click";
}
}

View File

@ -1,5 +1,14 @@
//! Utilities for [`dynatos`]
// Features
#![feature(decl_macro)]
// Modules
mod event_listener;
// Exports
pub use event_listener::{ev, ElementEventListener, EventListener};
// Imports
use {
std::fmt,