Merge branch 'upstream' into query-system

This commit is contained in:
Evan Almloff committed 2023-05-05 11:09:25 -05:00
commit 19436e210f
8 files changed
+63 -145

No files matched your search

+1 -2
View File
@@ -10,8 +10,7 @@ fn App(cx: Scope) -> Element {
// ANCHOR: prevent_default // ANCHOR: prevent_default
cx.render(rsx! { cx.render(rsx! {
input { input {
prevent_default: "oninput", prevent_default: "oninput onclick",
prevent_default: "onclick",
} }
}) })
// ANCHOR_END: prevent_default // ANCHOR_END: prevent_default
@@ -31,7 +31,7 @@ Some events will trigger first on the element the event originated at upward. Fo
> For more information about event propigation see [the mdn docs on event bubling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling) > For more information about event propigation see [the mdn docs on event bubling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
If you want to prevent this behavior, you can call `stop_propogation()` on the event: If you want to prevent this behavior, you can call `stop_propagation()` on the event:
```rust ```rust
{{#include ../../../examples/event_nested.rs:rsx}} {{#include ../../../examples/event_nested.rs:rsx}}
@@ -41,7 +41,7 @@ If you want to prevent this behavior, you can call `stop_propogation()` on the e
Some events have a default behavior. For keyboard events, this might be entering the typed character. For mouse events, this might be selecting some text. Some events have a default behavior. For keyboard events, this might be entering the typed character. For mouse events, this might be selecting some text.
In some instances, might want to avoid this default behavior. For this, you can add the `prevent_default` attribute with the name of the handler whose default behavior you want to stop. This attribute is special: you can attach it multiple times for multiple attributes: In some instances, might want to avoid this default behavior. For this, you can add the `prevent_default` attribute with the name of the handler whose default behavior you want to stop. This attribute can be used for multiple handlers using their name separated by spaces:
```rust ```rust
{{#include ../../../examples/event_prevent_default.rs:prevent_default}} {{#include ../../../examples/event_prevent_default.rs:prevent_default}}
File renamed without changes.
+4 -1
View File
@@ -4,7 +4,8 @@ use serde::Deserialize;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub(crate) struct FileDiologRequest { pub(crate) struct FileDiologRequest {
accept: String, #[serde(default)]
accept: Option<String>,
multiple: bool, multiple: bool,
pub event: String, pub event: String,
pub target: usize, pub target: usize,
@@ -16,6 +17,8 @@ pub(crate) fn get_file_event(request: &FileDiologRequest) -> Vec<PathBuf> {
let filters: Vec<_> = request let filters: Vec<_> = request
.accept .accept
.as_deref()
.unwrap_or_default()
.split(',') .split(',')
.filter_map(|s| Filters::from_str(s).ok()) .filter_map(|s| Filters::from_str(s).ok())
.collect(); .collect();
+8 -8
View File
@@ -15,12 +15,12 @@ fn module_loader(root_name: &str) -> String {
let inputs = document.querySelectorAll("input"); let inputs = document.querySelectorAll("input");
for (let input of inputs) { for (let input of inputs) {
if (!input.getAttribute("data-dioxus-file-listener")) { if (!input.getAttribute("data-dioxus-file-listener")) {
input.setAttribute("data-dioxus-file-listener", true); // prevent file inputs from opening the file dialog on click
input.addEventListener("click", (event) => { const type = input.getAttribute("type");
let target = event.target; if (type === "file") {
// prevent file inputs from opening the file dialog on click input.setAttribute("data-dioxus-file-listener", true);
const type = target.getAttribute("type"); input.addEventListener("click", (event) => {
if (type === "file") { let target = event.target;
let target_id = find_real_id(target); let target_id = find_real_id(target);
if (target_id !== null) { if (target_id !== null) {
const send = (event_name) => { const send = (event_name) => {
@@ -30,8 +30,8 @@ fn module_loader(root_name: &str) -> String {
send("change&input"); send("change&input");
} }
event.preventDefault(); event.preventDefault();
} });
}); }
} }
}"#, }"#,
); );
+5 -1
View File
@@ -14,7 +14,11 @@ pub struct FormData {
#[cfg_attr( #[cfg_attr(
feature = "serialize", feature = "serialize",
serde(skip_serializing, deserialize_with = "deserialize_file_engine") serde(
default,
skip_serializing,
deserialize_with = "deserialize_file_engine"
)
)] )]
pub files: Option<std::sync::Arc<dyn FileEngine>>, pub files: Option<std::sync::Arc<dyn FileEngine>>,
} }
+35 -127
View File
@@ -206,31 +206,25 @@ class Interpreter {
} }
GetClientRect(id) { GetClientRect(id) {
const node= this.nodes[id]; const node = this.nodes[id];
if (!node) { if (!node) {
return; return;
} }
const rect = node.getBoundingClientRect(); const rect = node.getBoundingClientRect();
return { return {
type: "GetClientRect", type: "GetClientRect",
origin: [ origin: [rect.x, rect.y],
rect.x, size: [rect.width, rect.height],
rect.y,
],
size: [
rect.width,
rect.height,
]
}; };
} }
ScrollTo(id, behavior) { ScrollTo(id, behavior) {
const node = this.nodes[id]; const node = this.nodes[id];
if (!node) { if (!node) {
return false; return false;
} }
node.scrollIntoView({ node.scrollIntoView({
behavior: behavior behavior: behavior,
}); });
return true; return true;
} }
@@ -248,7 +242,7 @@ class Interpreter {
} }
return true; return true;
} }
handleEdits(edits) { handleEdits(edits) {
for (let template of edits.templates) { for (let template of edits.templates) {
this.SaveTemplate(template); this.SaveTemplate(template);
@@ -393,113 +387,19 @@ class Interpreter {
// if this is a mounted listener, we send the event immediately // if this is a mounted listener, we send the event immediately
if (edit.name === "mounted") { if (edit.name === "mounted") {
window.ipc.postMessage( window.ipc.postMessage(
serializeIpcMessage("user_event", { serializeIpcMessage("user_event", {
name: edit.name, name: edit.name,
element: edit.id, element: edit.id,
data: null, data: null,
bubbles, bubbles,
}) })
); );
} else {
this.NewEventListener(edit.name, edit.id, bubbles, (event) => {
handler(event, edit.name, bubbles);
});
} }
// this handler is only provided on desktop implementations since this
// method is not used by the web implementation
let handler = (event) => {
let target = event.target;
if (target != null) {
let realId = target.getAttribute(`data-dioxus-id`);
let shouldPreventDefault = target.getAttribute(
`dioxus-prevent-default`
);
if (event.type === "click") {
// todo call prevent default if it's the right type of event
let a_element = target.closest("a");
if (a_element != null) {
event.preventDefault();
if (
shouldPreventDefault !== `onclick` &&
a_element.getAttribute(`dioxus-prevent-default`) !== `onclick`
) {
const href = a_element.getAttribute("href");
if (href !== "" && href !== null && href !== undefined) {
window.ipc.postMessage(
serializeIpcMessage("browser_open", { href })
);
}
}
}
// also prevent buttons from submitting
if (target.tagName === "BUTTON" && event.type == "submit") {
event.preventDefault();
}
}
// walk the tree to find the real element
while (realId == null) {
// we've reached the root we don't want to send an event
if (target.parentElement === null) {
return;
}
target = target.parentElement;
realId = target.getAttribute(`data-dioxus-id`);
}
shouldPreventDefault = target.getAttribute(
`dioxus-prevent-default`
);
let contents = serialize_event(event);
if (shouldPreventDefault === `on${event.type}`) {
event.preventDefault();
}
if (event.type === "submit") {
event.preventDefault();
}
if (
target.tagName === "FORM" &&
(event.type === "submit" || event.type === "input")
) {
for (let x = 0; x < target.elements.length; x++) {
let element = target.elements[x];
let name = element.getAttribute("name");
if (name != null) {
if (element.getAttribute("type") === "checkbox") {
// @ts-ignore
contents.values[name] = element.checked ? "true" : "false";
} else if (element.getAttribute("type") === "radio") {
if (element.checked) {
contents.values[name] = element.value;
}
} else {
// @ts-ignore
contents.values[name] =
element.value ?? element.textContent;
}
}
}
}
if (realId === null) {
return;
}
window.ipc.postMessage(
serializeIpcMessage("user_event", {
name: edit.name,
element: parseInt(realId),
data: contents,
bubbles,
})
);
}
};
this.NewEventListener(edit.name, edit.id, bubbles, handler);
break; break;
} }
} }
@@ -510,17 +410,24 @@ class Interpreter {
function handler(event, name, bubbles) { function handler(event, name, bubbles) {
let target = event.target; let target = event.target;
if (target != null) { if (target != null) {
let shouldPreventDefault = target.getAttribute(`dioxus-prevent-default`); let preventDefaultRequests = target.getAttribute(`dioxus-prevent-default`);
if (event.type === "click") { if (event.type === "click") {
// Prevent redirects from links // todo call prevent default if it's the right type of event
let a_element = target.closest("a"); let a_element = target.closest("a");
if (a_element != null) { if (a_element != null) {
event.preventDefault(); event.preventDefault();
if (
shouldPreventDefault !== `onclick` && let elementShouldPreventDefault =
a_element.getAttribute(`dioxus-prevent-default`) !== `onclick` preventDefaultRequests && preventDefaultRequests.includes(`onclick`);
) { let aElementShouldPreventDefault = a_element.getAttribute(
`dioxus-prevent-default`
);
let linkShouldPreventDefault =
aElementShouldPreventDefault &&
aElementShouldPreventDefault.includes(`onclick`);
if (!elementShouldPreventDefault && !linkShouldPreventDefault) {
const href = a_element.getAttribute("href"); const href = a_element.getAttribute("href");
if (href !== "" && href !== null && href !== undefined) { if (href !== "" && href !== null && href !== undefined) {
window.ipc.postMessage( window.ipc.postMessage(
@@ -538,9 +445,10 @@ function handler(event, name, bubbles) {
const realId = find_real_id(target); const realId = find_real_id(target);
shouldPreventDefault = target.getAttribute(`dioxus-prevent-default`); if (
preventDefaultRequests &&
if (shouldPreventDefault === `on${event.type}`) { preventDefaultRequests.includes(`on${event.type}`)
) {
event.preventDefault(); event.preventDefault();
} }
+8 -4
View File
@@ -56,13 +56,17 @@ impl WebsysDom {
let element = walk_event_for_id(event); let element = walk_event_for_id(event);
let bubbles = dioxus_html::event_bubbles(name.as_str()); let bubbles = dioxus_html::event_bubbles(name.as_str());
if let Some((element, target)) = element { if let Some((element, target)) = element {
if target if let Some(prevent_requests) = target
.get_attribute("dioxus-prevent-default") .get_attribute("dioxus-prevent-default")
.as_deref() .as_deref()
.map(|f| f.trim_start_matches("on")) .map(|f| f.split_whitespace())
== Some(&name)
{ {
event.prevent_default(); if prevent_requests
.map(|f| f.trim_start_matches("on"))
.any(|f| f == name)
{
event.prevent_default();
}
} }
let data = virtual_event_from_websys_event(event.clone(), target); let data = virtual_event_from_websys_event(event.clone(), target);