From be769e4e3ea564938d127c5440e2e168e0668fed Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Wed, 15 Jan 2025 10:42:50 +0100 Subject: [PATCH] Replace DragEvent data by a global state --- frontend/src/recipe_edit.rs | 78 +++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/frontend/src/recipe_edit.rs b/frontend/src/recipe_edit.rs index df491d7..9f5f721 100644 --- a/frontend/src/recipe_edit.rs +++ b/frontend/src/recipe_edit.rs @@ -1,4 +1,4 @@ -use std::rc; +use std::{cell::RefCell, rc, sync::Mutex}; use gloo::{ console::log, @@ -401,8 +401,9 @@ fn create_group_element(group: &ron_api::Group) -> Element { if modal_dialog::show(&format!("Are you sure to delete the group '{}'", name)).await { let body = ron_api::RemoveRecipeGroup { group_id }; let _ = request::delete::<(), _>("recipe/remove_group", body).await; - by_id::(&format!("group-{}", group_id)).remove(); - by_id::(&format!("dropzone-group-{}", group_id)).remove(); + let group_element = by_id::(&format!("group-{}", group_id)); + group_element.next_element_sibling().unwrap().remove(); + group_element.remove(); } }); }) @@ -534,8 +535,9 @@ fn create_step_element(group_element: &Element, step: &ron_api::Step) -> Element if modal_dialog::show(&format!("Are you sure to delete the step '{}'", action)).await { let body = ron_api::RemoveRecipeStep { step_id }; let _ = request::delete::<(), _>("recipe/remove_step", body).await; - by_id::(&format!("step-{}", step_id)).remove(); - by_id::(&format!("dropzone-step-{}", step_id)).remove(); + let step_element = by_id::(&format!("step-{}", step_id)); + step_element.next_element_sibling().unwrap().remove(); + step_element.remove(); } }); }) @@ -674,9 +676,6 @@ fn create_ingredient_element(step_element: &Element, ingredient: &ron_api::Ingre ingredient_element } -// "text/plain" is avoided to prevent dropping to a input text box. -const DRAG_AND_DROP_MIME_TYPE: &str = "recipes/element-id"; - enum CursorPosition { UpperPart, LowerPart, @@ -700,6 +699,12 @@ fn get_parent_with_id_starting_with(mut element: Element, prefix: &str) -> Eleme element } +// It replaces 'event.data_transfer().unwrap().get_data()/set_data()' because +// Chrome prevent to read this during draghover event which is the correct behavior +// according the specifications: +// * https://html.spec.whatwg.org/multipage/dnd.html#the-drag-data-store +static DATA_DRAGGED: Mutex> = Mutex::new(RefCell::new(String::new())); + /// Set an element as draggable and add an element before and after /// cloned from "#hidden-templates .dropzone". /// All elements set as draggable in a given container can be dragged @@ -731,11 +736,9 @@ where EventListenerOptions::enable_prevent_default(), move |event| { let event: &DragEvent = event.dyn_ref::().unwrap(); - let drag_data = event - .data_transfer() - .unwrap() - .get_data(DRAG_AND_DROP_MIME_TYPE) - .unwrap(); + + let drag_data_lock = DATA_DRAGGED.lock().unwrap(); + let drag_data = drag_data_lock.borrow(); if drag_data.starts_with(&prefix_copied) { let element: Element = by_id(&drag_data); @@ -777,11 +780,9 @@ where let prefix_copied = prefix.to_string(); EventListener::new(element, "dragleave", move |event| { let event: &DragEvent = event.dyn_ref::().unwrap(); - let drag_data = event - .data_transfer() - .unwrap() - .get_data(DRAG_AND_DROP_MIME_TYPE) - .unwrap(); + + let drag_data_lock = DATA_DRAGGED.lock().unwrap(); + let drag_data = drag_data_lock.borrow(); if drag_data.starts_with(&prefix_copied) { let element: Element = by_id(&drag_data); @@ -812,11 +813,9 @@ where let prefix_copied = prefix.to_string(); EventListener::new(element, "drop", move |event| { let event: &DragEvent = event.dyn_ref::().unwrap(); - let drag_data = event - .data_transfer() - .unwrap() - .get_data(DRAG_AND_DROP_MIME_TYPE) - .unwrap(); + + let drag_data_lock = DATA_DRAGGED.lock().unwrap(); + let drag_data = drag_data_lock.borrow(); if drag_data.starts_with(&prefix_copied) { let target: Element = event.current_target().unwrap().dyn_into().unwrap(); @@ -899,11 +898,10 @@ where dp.set_class_name("dropzone active"); } } - event - .data_transfer() - .unwrap() - .set_data(DRAG_AND_DROP_MIME_TYPE, &target_element.id()) - .unwrap(); + + let drag_data_lock = DATA_DRAGGED.lock().unwrap(); + drag_data_lock.replace(target_element.id()); + event.data_transfer().unwrap().set_effect_allowed("move"); } }) @@ -938,11 +936,9 @@ where EventListenerOptions::enable_prevent_default(), move |event| { let event: &DragEvent = event.dyn_ref::().unwrap(); - let drag_data = event - .data_transfer() - .unwrap() - .get_data(DRAG_AND_DROP_MIME_TYPE) - .unwrap(); + + let drag_data_lock = DATA_DRAGGED.lock().unwrap(); + let drag_data = drag_data_lock.borrow(); if drag_data.starts_with(&prefix_copied) { let element: Element = by_id(&drag_data); @@ -973,11 +969,9 @@ where let prefix_copied = prefix.to_string(); EventListener::new(dropzone, "dragleave", move |event| { let event: &DragEvent = event.dyn_ref::().unwrap(); - let drag_data = event - .data_transfer() - .unwrap() - .get_data(DRAG_AND_DROP_MIME_TYPE) - .unwrap(); + + let drag_data_lock = DATA_DRAGGED.lock().unwrap(); + let drag_data = drag_data_lock.borrow(); if drag_data.starts_with(&prefix_copied) { let element: Element = by_id(&drag_data); @@ -1005,11 +999,9 @@ where let prefix_copied = prefix.to_string(); EventListener::new(dropzone, "drop", move |event| { let event: &DragEvent = event.dyn_ref::().unwrap(); - let drag_data = event - .data_transfer() - .unwrap() - .get_data(DRAG_AND_DROP_MIME_TYPE) - .unwrap(); + + let drag_data_lock = DATA_DRAGGED.lock().unwrap(); + let drag_data = drag_data_lock.borrow(); if drag_data.starts_with(&prefix_copied) { let target: Element = event.current_target().unwrap().dyn_into().unwrap(); -- 2.49.0