|
@@ -10,15 +10,16 @@
|
|
|
use dioxus_core::{
|
|
|
BorrowedAttributeValue, ElementId, Mutation, Template, TemplateAttribute, TemplateNode,
|
|
|
};
|
|
|
-use dioxus_html::{event_bubbles, CompositionData, FormData};
|
|
|
+use dioxus_html::{event_bubbles, CompositionData, FileEngine, FormData};
|
|
|
use dioxus_interpreter_js::{save_template, Channel};
|
|
|
use futures_channel::mpsc;
|
|
|
+use js_sys::Array;
|
|
|
use rustc_hash::FxHashMap;
|
|
|
-use std::{any::Any, rc::Rc};
|
|
|
-use wasm_bindgen::{closure::Closure, JsCast};
|
|
|
-use web_sys::{Document, Element, Event, HtmlElement};
|
|
|
+use std::{any::Any, rc::Rc, sync::Arc};
|
|
|
+use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsCast};
|
|
|
+use web_sys::{console, Document, Element, Event, HtmlElement};
|
|
|
|
|
|
-use crate::Config;
|
|
|
+use crate::{file_engine::WebFileEngine, Config};
|
|
|
|
|
|
pub struct WebsysDom {
|
|
|
document: Document,
|
|
@@ -206,6 +207,7 @@ impl WebsysDom {
|
|
|
},
|
|
|
SetText { value, id } => i.set_text(id.0 as u32, value),
|
|
|
NewEventListener { name, id, .. } => {
|
|
|
+ console::log_1(&format!("new event listener: {}", name).into());
|
|
|
i.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8);
|
|
|
}
|
|
|
RemoveEventListener { name, id } => {
|
|
@@ -224,6 +226,7 @@ impl WebsysDom {
|
|
|
// We need tests that simulate clicks/etc and make sure every event type works.
|
|
|
pub fn virtual_event_from_websys_event(event: web_sys::Event, target: Element) -> Rc<dyn Any> {
|
|
|
use dioxus_html::events::*;
|
|
|
+ console::log_1(&event.clone().into());
|
|
|
|
|
|
match event.type_().as_str() {
|
|
|
"copy" | "cut" | "paste" => Rc::new(ClipboardData {}),
|
|
@@ -325,47 +328,53 @@ fn read_input_to_data(target: Element) -> Rc<FormData> {
|
|
|
|
|
|
// try to fill in form values
|
|
|
if let Some(form) = target.dyn_ref::<web_sys::HtmlFormElement>() {
|
|
|
- let elements = form.elements();
|
|
|
- for x in 0..elements.length() {
|
|
|
- let element = elements.item(x).unwrap();
|
|
|
- if let Some(name) = element.get_attribute("name") {
|
|
|
- let value: Option<String> = element
|
|
|
- .dyn_ref()
|
|
|
- .map(|input: &web_sys::HtmlInputElement| {
|
|
|
- match input.type_().as_str() {
|
|
|
- "checkbox" => {
|
|
|
- match input.checked() {
|
|
|
- true => Some("true".to_string()),
|
|
|
- false => Some("false".to_string()),
|
|
|
- }
|
|
|
- },
|
|
|
- "radio" => {
|
|
|
- match input.checked() {
|
|
|
- true => Some(input.value()),
|
|
|
- false => None,
|
|
|
- }
|
|
|
- }
|
|
|
- _ => Some(input.value())
|
|
|
- }
|
|
|
- })
|
|
|
- .or_else(|| element.dyn_ref().map(|input: &web_sys::HtmlTextAreaElement| Some(input.value())))
|
|
|
- .or_else(|| element.dyn_ref().map(|input: &web_sys::HtmlSelectElement| Some(input.value())))
|
|
|
- .or_else(|| Some(element.dyn_ref::<web_sys::HtmlElement>().unwrap().text_content()))
|
|
|
- .expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener");
|
|
|
- if let Some(value) = value {
|
|
|
- values.insert(name, value);
|
|
|
+ let form_data = get_form_data(form);
|
|
|
+ for value in form_data.entries().into_iter().flatten() {
|
|
|
+ if let Ok(array) = value.dyn_into::<Array>() {
|
|
|
+ if let Some(name) = array.get(0).as_string() {
|
|
|
+ if let Ok(item_values) = array.get(1).dyn_into::<Array>() {
|
|
|
+ let item_values =
|
|
|
+ item_values.iter().filter_map(|v| v.as_string()).collect();
|
|
|
+
|
|
|
+ values.insert(name, item_values);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ let files = target
|
|
|
+ .dyn_ref()
|
|
|
+ .and_then(|input: &web_sys::HtmlInputElement| {
|
|
|
+ input.files().and_then(|files| {
|
|
|
+ WebFileEngine::new(files).map(|f| Arc::new(f) as Arc<dyn FileEngine>)
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
Rc::new(FormData {
|
|
|
value,
|
|
|
values,
|
|
|
- files: None,
|
|
|
+ files,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// web-sys does not expose the keys api for form data, so we need to manually bind to it
|
|
|
+#[wasm_bindgen(inline_js = r#"
|
|
|
+ export function get_form_data(form) {
|
|
|
+ let values = new Map();
|
|
|
+ const formData = new FormData(form);
|
|
|
+
|
|
|
+ for (let name of formData.keys()) {
|
|
|
+ values.set(name, formData.getAll(name));
|
|
|
+ }
|
|
|
+
|
|
|
+ return values;
|
|
|
+ }
|
|
|
+"#)]
|
|
|
+extern "C" {
|
|
|
+ fn get_form_data(form: &web_sys::HtmlFormElement) -> js_sys::Map;
|
|
|
+}
|
|
|
+
|
|
|
fn walk_event_for_id(event: &web_sys::Event) -> Option<(ElementId, web_sys::Element)> {
|
|
|
let mut target = event
|
|
|
.target()
|