Browse Source

fix: dioxus web prevents default on in nested targets

this commit fixes an issue where we used the event target to
prevent default even if the target element wasn't an event
handler.
Jonathan Kelley 3 years ago
parent
commit
8badf90a03
1 changed files with 47 additions and 53 deletions
  1. 47 53
      packages/web/src/dom.rs

+ 47 - 53
packages/web/src/dom.rs

@@ -28,17 +28,54 @@ impl WebsysDom {
     pub fn new(cfg: WebConfig, sender_callback: Rc<dyn Fn(SchedulerMsg)>) -> Self {
         // eventually, we just want to let the interpreter do all the work of decoding events into our event type
         let callback: Box<dyn FnMut(&Event)> = Box::new(move |event: &web_sys::Event| {
-            if let Ok(synthetic_event) = decode_trigger(event) {
+            let mut target = event
+                .target()
+                .expect("missing target")
+                .dyn_into::<Element>()
+                .expect("not a valid element");
+
+            let typ = event.type_();
+
+            let decoded: anyhow::Result<UserEvent> = loop {
+                match target.get_attribute("data-dioxus-id").map(|f| f.parse()) {
+                    Some(Ok(id)) => {
+                        break Ok(UserEvent {
+                            name: event_name_from_typ(&typ),
+                            data: virtual_event_from_websys_event(event.clone()),
+                            element: Some(ElementId(id)),
+                            scope_id: None,
+                            priority: dioxus_core::EventPriority::Medium,
+                        });
+                    }
+                    Some(Err(e)) => {
+                        break Err(e.into());
+                    }
+                    None => {
+                        // walk the tree upwards until we actually find an event target
+                        if let Some(parent) = target.parent_element() {
+                            target = parent;
+                        } else {
+                            break Ok(UserEvent {
+                                name: event_name_from_typ(&typ),
+                                data: virtual_event_from_websys_event(event.clone()),
+                                element: None,
+                                scope_id: None,
+                                priority: dioxus_core::EventPriority::Low,
+                            });
+                        }
+                    }
+                }
+            };
+
+            if let Ok(synthetic_event) = decoded {
                 // Try to prevent default if the attribute is set
-                if let Some(target) = event.target() {
-                    if let Some(node) = target.dyn_ref::<HtmlElement>() {
-                        if let Some(name) = node.get_attribute("dioxus-prevent-default") {
-                            if name == synthetic_event.name
-                                || name.trim_start_matches("on") == synthetic_event.name
-                            {
-                                log::trace!("Preventing default");
-                                event.prevent_default();
-                            }
+                if let Some(node) = target.dyn_ref::<HtmlElement>() {
+                    if let Some(name) = node.get_attribute("dioxus-prevent-default") {
+                        if name == synthetic_event.name
+                            || name.trim_start_matches("on") == synthetic_event.name
+                        {
+                            log::trace!("Preventing default");
+                            event.prevent_default();
                         }
                     }
                 }
@@ -274,49 +311,6 @@ fn virtual_event_from_websys_event(event: web_sys::Event) -> Arc<dyn Any + Send
     }
 }
 
-/// This function decodes a websys event and produces an EventTrigger
-/// With the websys implementation, we attach a unique key to the nodes
-fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<UserEvent> {
-    let mut target = event
-        .target()
-        .expect("missing target")
-        .dyn_into::<Element>()
-        .expect("not a valid element");
-
-    let typ = event.type_();
-
-    loop {
-        match target.get_attribute("data-dioxus-id").map(|f| f.parse()) {
-            Some(Ok(id)) => {
-                return Ok(UserEvent {
-                    name: event_name_from_typ(&typ),
-                    data: virtual_event_from_websys_event(event.clone()),
-                    element: Some(ElementId(id)),
-                    scope_id: None,
-                    priority: dioxus_core::EventPriority::Medium,
-                });
-            }
-            Some(Err(e)) => {
-                return Err(e.into());
-            }
-            None => {
-                // walk the tree upwards until we actually find an event target
-                if let Some(parent) = target.parent_element() {
-                    target = parent;
-                } else {
-                    return Ok(UserEvent {
-                        name: event_name_from_typ(&typ),
-                        data: virtual_event_from_websys_event(event.clone()),
-                        element: None,
-                        scope_id: None,
-                        priority: dioxus_core::EventPriority::Low,
-                    });
-                }
-            }
-        }
-    }
-}
-
 pub(crate) fn load_document() -> Document {
     web_sys::window()
         .expect("should have access to the Window")