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.
This commit is contained in:
1 parent
fb75948363
commit
8badf90a03
1 file changed
+47
-53
+47
-53
@@ -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")
|
||||
|
||||
Reference in new issue
Block a user