ソースを参照

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 年 前
コミット
8badf90a03
1 ファイル変更47 行追加53 行削除
  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 {
     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
         // 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| {
         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
                 // 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 {
 pub(crate) fn load_document() -> Document {
     web_sys::window()
     web_sys::window()
         .expect("should have access to the Window")
         .expect("should have access to the Window")