diff --git a/src/bindings.rs b/src/bindings.rs
index 6e66ad2..b0e643f 100644
--- a/src/bindings.rs
+++ b/src/bindings.rs
@@ -7,32 +7,24 @@ use web_sys::{HtmlElement, Element, Node, Window, History, Document, Text, Comme
#[wasm_bindgen(inline_js = "
export function set_property(obj, name, value) { obj[name] = value; }
- export function add_event(elem, name, f) {
+ export function add_event(elem, name, capture, passive, f) {
elem.addEventListener(name, f, {
- capture: true,
+ capture,
+ passive,
once: false,
- passive: true
});
}
export function add_event_once(elem, name, f) {
elem.addEventListener(name, f, {
capture: true,
- once: true,
passive: true,
+ once: true,
});
}
- export function add_event_preventable(elem, name, f) {
- elem.addEventListener(name, f, {
- capture: true,
- once: false,
- passive: false
- });
- }
-
- export function remove_event(elem, name, f) {
- elem.removeEventListener(name, f, true);
+ export function remove_event(elem, name, capture, f) {
+ elem.removeEventListener(name, f, capture);
}
")]
extern "C" {
@@ -41,10 +33,9 @@ extern "C" {
pub(crate) fn set_property(obj: &JsValue, name: &str, value: &JsValue);
// TODO replace with gloo-events
- pub(crate) fn add_event(elem: &EventTarget, name: &str, f: &Function);
+ pub(crate) fn add_event(elem: &EventTarget, name: &str, capture: bool, passive: bool, f: &Function);
pub(crate) fn add_event_once(elem: &EventTarget, name: &str, f: &Function);
- pub(crate) fn add_event_preventable(elem: &EventTarget, name: &str, f: &Function);
- pub(crate) fn remove_event(elem: &EventTarget, name: &str, f: &Function);
+ pub(crate) fn remove_event(elem: &EventTarget, name: &str, capture: bool, f: &Function);
}
diff --git a/src/dom.rs b/src/dom.rs
index eba5afa..e623bea 100644
--- a/src/dom.rs
+++ b/src/dom.rs
@@ -18,7 +18,7 @@ use crate::callbacks::Callbacks;
use crate::traits::*;
use crate::operations;
use crate::operations::{for_each, spawn_future};
-use crate::utils::{EventListener, on, on_preventable, ValueDiscard, FnDiscard};
+use crate::utils::{EventListener, on, ValueDiscard, FnDiscard};
pub struct RefFn where B: ?Sized, C: Fn(&A) -> &B {
@@ -408,6 +408,38 @@ fn set_property(element: &A, name: &B, value: C) where A: AsRef Self {
+ Self {
+ bubbles: true,
+ preventable: false,
+ }
+ }
+
+ pub fn preventable() -> Self {
+ Self {
+ bubbles: false,
+ preventable: true,
+ }
+ }
+}
+
+impl Default for EventOptions {
+ fn default() -> Self {
+ Self {
+ bubbles: false,
+ preventable: false,
+ }
+ }
+}
+
+
// TODO better warning message for must_use
#[must_use]
pub struct DomBuilder {
@@ -445,17 +477,19 @@ impl DomBuilder {
}
#[inline]
- fn _event(&mut self, element: EventTarget, listener: F)
+ fn _event(&mut self, element: EventTarget, options: &EventOptions, listener: F)
where T: StaticEvent,
F: FnMut(T) + 'static {
- self.callbacks.after_remove(on(element, listener));
+ self.callbacks.after_remove(on(element, options, listener));
}
+ // TODO add this to the StylesheetBuilder and ClassBuilder too
#[inline]
- fn _event_preventable(&mut self, element: EventTarget, listener: F)
+ pub fn global_event_with_options(mut self, options: &EventOptions, listener: F) -> Self
where T: StaticEvent,
F: FnMut(T) + 'static {
- self.callbacks.after_remove(on_preventable(element, listener));
+ self._event(bindings::window_event_target(), options, listener);
+ self
}
// TODO add this to the StylesheetBuilder and ClassBuilder too
@@ -463,17 +497,16 @@ impl DomBuilder {
pub fn global_event(mut self, listener: F) -> Self
where T: StaticEvent,
F: FnMut(T) + 'static {
- self._event(bindings::window_event_target(), listener);
- self
+ self.global_event_with_options(&EventOptions::default(), listener)
}
// TODO add this to the StylesheetBuilder and ClassBuilder too
+ #[deprecated(since = "0.5.21", note = "Use global_event_with_options instead")]
#[inline]
pub fn global_event_preventable(mut self, listener: F) -> Self
where T: StaticEvent,
F: FnMut(T) + 'static {
- self._event_preventable(bindings::window_event_target(), listener);
- self
+ self.global_event_with_options(&EventOptions::preventable(), listener)
}
#[inline]
@@ -598,21 +631,27 @@ impl DomBuilder where A: AsRef {
impl DomBuilder where A: AsRef {
#[inline]
- pub fn event(mut self, listener: F) -> Self
+ pub fn event_with_options(mut self, options: &EventOptions, listener: F) -> Self
where T: StaticEvent,
F: FnMut(T) + 'static {
// TODO can this clone be avoided ?
- self._event(self.element.as_ref().clone(), listener);
+ self._event(self.element.as_ref().clone(), options, listener);
self
}
#[inline]
- pub fn event_preventable(mut self, listener: F) -> Self
+ pub fn event(self, listener: F) -> Self
where T: StaticEvent,
F: FnMut(T) + 'static {
- // TODO can this clone be avoided ?
- self._event_preventable(self.element.as_ref().clone(), listener);
- self
+ self.event_with_options(&EventOptions::default(), listener)
+ }
+
+ #[deprecated(since = "0.5.21", note = "Use event_with_options instead")]
+ #[inline]
+ pub fn event_preventable(self, listener: F) -> Self
+ where T: StaticEvent,
+ F: FnMut(T) + 'static {
+ self.event_with_options(&EventOptions::preventable(), listener)
}
}
diff --git a/src/routing.rs b/src/routing.rs
index a72b4fe..68f950a 100644
--- a/src/routing.rs
+++ b/src/routing.rs
@@ -5,7 +5,7 @@ use once_cell::sync::Lazy;
use futures_signals::signal::{Mutable, ReadOnlyMutable};
use crate::bindings;
-use crate::dom::{Dom, DomBuilder};
+use crate::dom::{Dom, DomBuilder, EventOptions};
use crate::utils::EventListener;
use crate::events;
@@ -34,7 +34,7 @@ impl CurrentUrl {
let value = Mutable::new(String::from(bindings::current_url()));
// TODO clean this up somehow ?
- let _ = EventListener::new(bindings::window_event_target(), "popstate", {
+ let _ = EventListener::new(bindings::window_event_target(), "popstate", &EventOptions::default(), {
let value = value.clone();
move |_| {
change_url(&value);
diff --git a/src/utils.rs b/src/utils.rs
index f723283..3e662bd 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -6,6 +6,7 @@ use discard::Discard;
use web_sys::{EventTarget, Event};
use crate::bindings;
+use crate::dom::EventOptions;
use crate::traits::StaticEvent;
@@ -13,29 +14,22 @@ use crate::traits::StaticEvent;
pub(crate) struct EventListener {
elem: EventTarget,
name: &'static str,
+ capture: bool,
closure: Option>,
}
// TODO should these inline ?
impl EventListener {
#[inline]
- pub(crate) fn new(elem: EventTarget, name: &'static str, callback: F) -> Self where F: FnMut(&Event) + 'static {
+ pub(crate) fn new(elem: EventTarget, name: &'static str, options: &EventOptions, callback: F) -> Self where F: FnMut(&Event) + 'static {
let closure = Closure::wrap(Box::new(callback) as Box);
let name: &'static str = intern(name);
- bindings::add_event(&elem, name, closure.as_ref().unchecked_ref());
+ let capture = !options.bubbles;
- Self { elem, name, closure: Some(closure) }
- }
+ bindings::add_event(&elem, name, capture, !options.preventable, closure.as_ref().unchecked_ref());
- #[inline]
- pub(crate) fn new_preventable(elem: EventTarget, name: &'static str, callback: F) -> Self where F: FnMut(&Event) + 'static {
- let closure = Closure::wrap(Box::new(callback) as Box);
- let name: &'static str = intern(name);
-
- bindings::add_event_preventable(&elem, name, closure.as_ref().unchecked_ref());
-
- Self { elem, name, closure: Some(closure) }
+ Self { elem, name, capture, closure: Some(closure) }
}
#[inline]
@@ -45,7 +39,7 @@ impl EventListener {
bindings::add_event_once(&elem, name, closure.as_ref().unchecked_ref());
- Self { elem, name, closure: Some(closure) }
+ Self { elem, name, capture: true, closure: Some(closure) }
}
}
@@ -63,25 +57,16 @@ impl Discard for EventListener {
#[inline]
fn discard(mut self) {
let closure = self.closure.take().unwrap_throw();
- bindings::remove_event(&self.elem, &self.name, closure.as_ref().unchecked_ref());
+ bindings::remove_event(&self.elem, &self.name, self.capture, closure.as_ref().unchecked_ref());
}
}
#[inline]
-pub(crate) fn on(element: EventTarget, mut callback: F) -> EventListener
+pub(crate) fn on(element: EventTarget, options: &EventOptions, mut callback: F) -> EventListener
where E: StaticEvent,
F: FnMut(E) + 'static {
- EventListener::new(element, E::EVENT_TYPE, move |e| {
- callback(E::unchecked_from_event(e.clone()));
- })
-}
-
-#[inline]
-pub(crate) fn on_preventable(element: EventTarget, mut callback: F) -> EventListener
- where E: StaticEvent,
- F: FnMut(E) + 'static {
- EventListener::new_preventable(element, E::EVENT_TYPE, move |e| {
+ EventListener::new(element, E::EVENT_TYPE, options, move |e| {
callback(E::unchecked_from_event(e.clone()));
})
}