mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-11 15:07:08 +00:00
Merge pull request #452 from Demonthos/fix_nonbubbling_web_events
Fix nonbubbling web events
This commit is contained in:
commit
83288e274f
10 changed files with 368 additions and 27 deletions
|
@ -63,6 +63,9 @@ pub struct UserEvent {
|
||||||
/// The event type IE "onclick" or "onmouseover"
|
/// The event type IE "onclick" or "onmouseover"
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
|
|
||||||
|
/// If the event is bubbles up through the vdom
|
||||||
|
pub bubbles: bool,
|
||||||
|
|
||||||
/// The event data to be passed onto the event handler
|
/// The event data to be passed onto the event handler
|
||||||
pub data: Arc<dyn Any + Send + Sync>,
|
pub data: Arc<dyn Any + Send + Sync>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,7 +335,7 @@ impl ScopeArena {
|
||||||
log::trace!("calling listener {:?}", listener.event);
|
log::trace!("calling listener {:?}", listener.event);
|
||||||
if state.canceled.get() {
|
if state.canceled.get() {
|
||||||
// stop bubbling if canceled
|
// stop bubbling if canceled
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cb = listener.callback.borrow_mut();
|
let mut cb = listener.callback.borrow_mut();
|
||||||
|
@ -349,6 +349,10 @@ impl ScopeArena {
|
||||||
data: event.data.clone(),
|
data: event.data.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !event.bubbles {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::any::Any;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dioxus_core::{ElementId, EventPriority, UserEvent};
|
use dioxus_core::{ElementId, EventPriority, UserEvent};
|
||||||
|
use dioxus_html::event_bubbles;
|
||||||
use dioxus_html::on::*;
|
use dioxus_html::on::*;
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
@ -47,8 +48,8 @@ pub fn trigger_from_serialized(val: serde_json::Value) -> UserEvent {
|
||||||
} = serde_json::from_value(val).unwrap();
|
} = serde_json::from_value(val).unwrap();
|
||||||
|
|
||||||
let mounted_dom_id = Some(ElementId(mounted_dom_id as usize));
|
let mounted_dom_id = Some(ElementId(mounted_dom_id as usize));
|
||||||
|
|
||||||
let name = event_name_from_type(&event);
|
let name = event_name_from_type(&event);
|
||||||
|
|
||||||
let event = make_synthetic_event(&event, contents);
|
let event = make_synthetic_event(&event, contents);
|
||||||
|
|
||||||
UserEvent {
|
UserEvent {
|
||||||
|
@ -56,6 +57,7 @@ pub fn trigger_from_serialized(val: serde_json::Value) -> UserEvent {
|
||||||
priority: EventPriority::Low,
|
priority: EventPriority::Low,
|
||||||
scope_id: None,
|
scope_id: None,
|
||||||
element: mounted_dom_id,
|
element: mounted_dom_id,
|
||||||
|
bubbles: event_bubbles(name),
|
||||||
data: event,
|
data: event,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1324,3 +1324,91 @@ pub(crate) fn _event_meta(event: &UserEvent) -> (bool, EventPriority) {
|
||||||
_ => (true, Low),
|
_ => (true, Low),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn event_bubbles(evt: &str) -> bool {
|
||||||
|
match evt {
|
||||||
|
"copy" => true,
|
||||||
|
"cut" => true,
|
||||||
|
"paste" => true,
|
||||||
|
"compositionend" => true,
|
||||||
|
"compositionstart" => true,
|
||||||
|
"compositionupdate" => true,
|
||||||
|
"keydown" => true,
|
||||||
|
"keypress" => true,
|
||||||
|
"keyup" => true,
|
||||||
|
"focus" => false,
|
||||||
|
"focusout" => true,
|
||||||
|
"focusin" => true,
|
||||||
|
"blur" => false,
|
||||||
|
"change" => true,
|
||||||
|
"input" => true,
|
||||||
|
"invalid" => true,
|
||||||
|
"reset" => true,
|
||||||
|
"submit" => true,
|
||||||
|
"click" => true,
|
||||||
|
"contextmenu" => true,
|
||||||
|
"doubleclick" => true,
|
||||||
|
"dblclick" => true,
|
||||||
|
"drag" => true,
|
||||||
|
"dragend" => true,
|
||||||
|
"dragenter" => false,
|
||||||
|
"dragexit" => false,
|
||||||
|
"dragleave" => true,
|
||||||
|
"dragover" => true,
|
||||||
|
"dragstart" => true,
|
||||||
|
"drop" => true,
|
||||||
|
"mousedown" => true,
|
||||||
|
"mouseenter" => false,
|
||||||
|
"mouseleave" => false,
|
||||||
|
"mousemove" => true,
|
||||||
|
"mouseout" => true,
|
||||||
|
"scroll" => false,
|
||||||
|
"mouseover" => true,
|
||||||
|
"mouseup" => true,
|
||||||
|
"pointerdown" => true,
|
||||||
|
"pointermove" => true,
|
||||||
|
"pointerup" => true,
|
||||||
|
"pointercancel" => true,
|
||||||
|
"gotpointercapture" => true,
|
||||||
|
"lostpointercapture" => true,
|
||||||
|
"pointerenter" => false,
|
||||||
|
"pointerleave" => false,
|
||||||
|
"pointerover" => true,
|
||||||
|
"pointerout" => true,
|
||||||
|
"select" => true,
|
||||||
|
"touchcancel" => true,
|
||||||
|
"touchend" => true,
|
||||||
|
"touchmove" => true,
|
||||||
|
"touchstart" => true,
|
||||||
|
"wheel" => true,
|
||||||
|
"abort" => false,
|
||||||
|
"canplay" => true,
|
||||||
|
"canplaythrough" => true,
|
||||||
|
"durationchange" => true,
|
||||||
|
"emptied" => true,
|
||||||
|
"encrypted" => true,
|
||||||
|
"ended" => true,
|
||||||
|
"error" => false,
|
||||||
|
"loadeddata" => true,
|
||||||
|
"loadedmetadata" => true,
|
||||||
|
"loadstart" => false,
|
||||||
|
"pause" => true,
|
||||||
|
"play" => true,
|
||||||
|
"playing" => true,
|
||||||
|
"progress" => false,
|
||||||
|
"ratechange" => true,
|
||||||
|
"seeked" => true,
|
||||||
|
"seeking" => true,
|
||||||
|
"stalled" => true,
|
||||||
|
"suspend" => true,
|
||||||
|
"timeupdate" => true,
|
||||||
|
"volumechange" => true,
|
||||||
|
"waiting" => true,
|
||||||
|
"animationstart" => true,
|
||||||
|
"animationend" => true,
|
||||||
|
"animationiteration" => true,
|
||||||
|
"transitionend" => true,
|
||||||
|
"toggle" => true,
|
||||||
|
_ => panic!("unsupported event type {:?}", evt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -48,10 +48,16 @@ extern "C" {
|
||||||
pub fn CreatePlaceholder(this: &Interpreter, root: u64);
|
pub fn CreatePlaceholder(this: &Interpreter, root: u64);
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub fn NewEventListener(this: &Interpreter, name: &str, root: u64, handler: &Function);
|
pub fn NewEventListener(
|
||||||
|
this: &Interpreter,
|
||||||
|
name: &str,
|
||||||
|
root: u64,
|
||||||
|
handler: &Function,
|
||||||
|
bubbles: bool,
|
||||||
|
);
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub fn RemoveEventListener(this: &Interpreter, root: u64, name: &str);
|
pub fn RemoveEventListener(this: &Interpreter, root: u64, name: &str, bubbles: bool);
|
||||||
|
|
||||||
#[wasm_bindgen(method)]
|
#[wasm_bindgen(method)]
|
||||||
pub fn SetText(this: &Interpreter, root: u64, text: JsValue);
|
pub fn SetText(this: &Interpreter, root: u64, text: JsValue);
|
||||||
|
|
|
@ -5,11 +5,64 @@ export function main() {
|
||||||
window.ipc.postMessage(serializeIpcMessage("initialize"));
|
window.ipc.postMessage(serializeIpcMessage("initialize"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ListenerMap {
|
||||||
|
constructor(root) {
|
||||||
|
// bubbling events can listen at the root element
|
||||||
|
this.global = {};
|
||||||
|
// non bubbling events listen at the element the listener was created at
|
||||||
|
this.local = {};
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
createBubbling(event_name, handler) {
|
||||||
|
if (this.global[event_name] === undefined) {
|
||||||
|
this.global[event_name] = {};
|
||||||
|
this.global[event_name].active = 1;
|
||||||
|
this.global[event_name].callback = handler;
|
||||||
|
this.root.addEventListener(event_name, handler);
|
||||||
|
} else {
|
||||||
|
this.global[event_name].active++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createNonBubbling(event_name, element, handler) {
|
||||||
|
const id = element.getAttribute("data-dioxus-id");
|
||||||
|
if (!this.local[id]) {
|
||||||
|
this.local[id] = {};
|
||||||
|
}
|
||||||
|
this.local[id][event_name] = handler;
|
||||||
|
element.addEventListener(event_name, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBubbling(event_name) {
|
||||||
|
this.global[event_name].active--;
|
||||||
|
if (this.global[event_name].active === 0) {
|
||||||
|
this.root.removeEventListener(event_name, this.global[event_name].callback);
|
||||||
|
delete this.global[event_name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeNonBubbling(element, event_name) {
|
||||||
|
const id = element.getAttribute("data-dioxus-id");
|
||||||
|
delete this.local[id][event_name];
|
||||||
|
if (this.local[id].length === 0) {
|
||||||
|
delete this.local[id];
|
||||||
|
}
|
||||||
|
element.removeEventListener(event_name, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeAllNonBubbling(element) {
|
||||||
|
const id = element.getAttribute("data-dioxus-id");
|
||||||
|
delete this.local[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Interpreter {
|
export class Interpreter {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
this.stack = [root];
|
this.stack = [root];
|
||||||
this.listeners = {};
|
this.listeners = new ListenerMap(root);
|
||||||
this.handlers = {};
|
this.handlers = {};
|
||||||
this.lastNodeWasText = false;
|
this.lastNodeWasText = false;
|
||||||
this.nodes = [root];
|
this.nodes = [root];
|
||||||
|
@ -40,6 +93,7 @@ export class Interpreter {
|
||||||
ReplaceWith(root_id, m) {
|
ReplaceWith(root_id, m) {
|
||||||
let root = this.nodes[root_id];
|
let root = this.nodes[root_id];
|
||||||
let els = this.stack.splice(this.stack.length - m);
|
let els = this.stack.splice(this.stack.length - m);
|
||||||
|
this.listeners.removeAllNonBubbling(root);
|
||||||
root.replaceWith(...els);
|
root.replaceWith(...els);
|
||||||
}
|
}
|
||||||
InsertAfter(root, n) {
|
InsertAfter(root, n) {
|
||||||
|
@ -54,6 +108,7 @@ export class Interpreter {
|
||||||
}
|
}
|
||||||
Remove(root) {
|
Remove(root) {
|
||||||
let node = this.nodes[root];
|
let node = this.nodes[root];
|
||||||
|
this.listeners.removeAllNonBubbling(node);
|
||||||
if (node !== undefined) {
|
if (node !== undefined) {
|
||||||
node.remove();
|
node.remove();
|
||||||
}
|
}
|
||||||
|
@ -79,25 +134,24 @@ export class Interpreter {
|
||||||
this.stack.push(el);
|
this.stack.push(el);
|
||||||
this.nodes[root] = el;
|
this.nodes[root] = el;
|
||||||
}
|
}
|
||||||
NewEventListener(event_name, root, handler) {
|
NewEventListener(event_name, root, handler, bubbles) {
|
||||||
const element = this.nodes[root];
|
const element = this.nodes[root];
|
||||||
element.setAttribute("data-dioxus-id", `${root}`);
|
element.setAttribute("data-dioxus-id", `${root}`);
|
||||||
if (this.listeners[event_name] === undefined) {
|
if (bubbles) {
|
||||||
this.listeners[event_name] = 1;
|
this.listeners.createBubbling(event_name, handler);
|
||||||
this.handlers[event_name] = handler;
|
}
|
||||||
this.root.addEventListener(event_name, handler);
|
else {
|
||||||
} else {
|
this.listeners.createNonBubbling(event_name, element, handler);
|
||||||
this.listeners[event_name]++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RemoveEventListener(root, event_name) {
|
RemoveEventListener(root, event_name, bubbles) {
|
||||||
const element = this.nodes[root];
|
const element = this.nodes[root];
|
||||||
element.removeAttribute(`data-dioxus-id`);
|
element.removeAttribute(`data-dioxus-id`);
|
||||||
this.listeners[event_name]--;
|
if (bubbles) {
|
||||||
if (this.listeners[event_name] === 0) {
|
this.listeners.removeBubbling(event_name)
|
||||||
this.root.removeEventListener(event_name, this.handlers[event_name]);
|
}
|
||||||
delete this.listeners[event_name];
|
else {
|
||||||
delete this.handlers[event_name];
|
this.listeners.removeNonBubbling(element, event_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetText(root, text) {
|
SetText(root, text) {
|
||||||
|
@ -198,12 +252,9 @@ export class Interpreter {
|
||||||
this.RemoveEventListener(edit.root, edit.event_name);
|
this.RemoveEventListener(edit.root, edit.event_name);
|
||||||
break;
|
break;
|
||||||
case "NewEventListener":
|
case "NewEventListener":
|
||||||
console.log(this.listeners);
|
|
||||||
|
|
||||||
// this handler is only provided on desktop implementations since this
|
// this handler is only provided on desktop implementations since this
|
||||||
// method is not used by the web implementation
|
// method is not used by the web implementation
|
||||||
let handler = (event) => {
|
let handler = (event) => {
|
||||||
console.log(event);
|
|
||||||
|
|
||||||
let target = event.target;
|
let target = event.target;
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
|
@ -292,7 +343,8 @@ export class Interpreter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.NewEventListener(edit.event_name, edit.root, handler);
|
this.NewEventListener(edit.event_name, edit.root, handler, event_bubbles(edit.event_name));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "SetText":
|
case "SetText":
|
||||||
this.SetText(edit.root, edit.text);
|
this.SetText(edit.root, edit.text);
|
||||||
|
@ -607,3 +659,172 @@ const bool_attrs = {
|
||||||
selected: true,
|
selected: true,
|
||||||
truespeed: true,
|
truespeed: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function event_bubbles(event) {
|
||||||
|
switch (event) {
|
||||||
|
case "copy":
|
||||||
|
return true;
|
||||||
|
case "cut":
|
||||||
|
return true;
|
||||||
|
case "paste":
|
||||||
|
return true;
|
||||||
|
case "compositionend":
|
||||||
|
return true;
|
||||||
|
case "compositionstart":
|
||||||
|
return true;
|
||||||
|
case "compositionupdate":
|
||||||
|
return true;
|
||||||
|
case "keydown":
|
||||||
|
return true;
|
||||||
|
case "keypress":
|
||||||
|
return true;
|
||||||
|
case "keyup":
|
||||||
|
return true;
|
||||||
|
case "focus":
|
||||||
|
return false;
|
||||||
|
case "focusout":
|
||||||
|
return true;
|
||||||
|
case "focusin":
|
||||||
|
return true;
|
||||||
|
case "blur":
|
||||||
|
return false;
|
||||||
|
case "change":
|
||||||
|
return true;
|
||||||
|
case "input":
|
||||||
|
return true;
|
||||||
|
case "invalid":
|
||||||
|
return true;
|
||||||
|
case "reset":
|
||||||
|
return true;
|
||||||
|
case "submit":
|
||||||
|
return true;
|
||||||
|
case "click":
|
||||||
|
return true;
|
||||||
|
case "contextmenu":
|
||||||
|
return true;
|
||||||
|
case "doubleclick":
|
||||||
|
return true;
|
||||||
|
case "dblclick":
|
||||||
|
return true;
|
||||||
|
case "drag":
|
||||||
|
return true;
|
||||||
|
case "dragend":
|
||||||
|
return true;
|
||||||
|
case "dragenter":
|
||||||
|
return false;
|
||||||
|
case "dragexit":
|
||||||
|
return false;
|
||||||
|
case "dragleave":
|
||||||
|
return true;
|
||||||
|
case "dragover":
|
||||||
|
return true;
|
||||||
|
case "dragstart":
|
||||||
|
return true;
|
||||||
|
case "drop":
|
||||||
|
return true;
|
||||||
|
case "mousedown":
|
||||||
|
return true;
|
||||||
|
case "mouseenter":
|
||||||
|
return false;
|
||||||
|
case "mouseleave":
|
||||||
|
return false;
|
||||||
|
case "mousemove":
|
||||||
|
return true;
|
||||||
|
case "mouseout":
|
||||||
|
return true;
|
||||||
|
case "scroll":
|
||||||
|
return false;
|
||||||
|
case "mouseover":
|
||||||
|
return true;
|
||||||
|
case "mouseup":
|
||||||
|
return true;
|
||||||
|
case "pointerdown":
|
||||||
|
return true;
|
||||||
|
case "pointermove":
|
||||||
|
return true;
|
||||||
|
case "pointerup":
|
||||||
|
return true;
|
||||||
|
case "pointercancel":
|
||||||
|
return true;
|
||||||
|
case "gotpointercapture":
|
||||||
|
return true;
|
||||||
|
case "lostpointercapture":
|
||||||
|
return true;
|
||||||
|
case "pointerenter":
|
||||||
|
return false;
|
||||||
|
case "pointerleave":
|
||||||
|
return false;
|
||||||
|
case "pointerover":
|
||||||
|
return true;
|
||||||
|
case "pointerout":
|
||||||
|
return true;
|
||||||
|
case "select":
|
||||||
|
return true;
|
||||||
|
case "touchcancel":
|
||||||
|
return true;
|
||||||
|
case "touchend":
|
||||||
|
return true;
|
||||||
|
case "touchmove":
|
||||||
|
return true;
|
||||||
|
case "touchstart":
|
||||||
|
return true;
|
||||||
|
case "wheel":
|
||||||
|
return true;
|
||||||
|
case "abort":
|
||||||
|
return false;
|
||||||
|
case "canplay":
|
||||||
|
return true;
|
||||||
|
case "canplaythrough":
|
||||||
|
return true;
|
||||||
|
case "durationchange":
|
||||||
|
return true;
|
||||||
|
case "emptied":
|
||||||
|
return true;
|
||||||
|
case "encrypted":
|
||||||
|
return true;
|
||||||
|
case "ended":
|
||||||
|
return true;
|
||||||
|
case "error":
|
||||||
|
return false;
|
||||||
|
case "loadeddata":
|
||||||
|
return true;
|
||||||
|
case "loadedmetadata":
|
||||||
|
return true;
|
||||||
|
case "loadstart":
|
||||||
|
return false;
|
||||||
|
case "pause":
|
||||||
|
return true;
|
||||||
|
case "play":
|
||||||
|
return true;
|
||||||
|
case "playing":
|
||||||
|
return true;
|
||||||
|
case "progress":
|
||||||
|
return false;
|
||||||
|
case "ratechange":
|
||||||
|
return true;
|
||||||
|
case "seeked":
|
||||||
|
return true;
|
||||||
|
case "seeking":
|
||||||
|
return true;
|
||||||
|
case "stalled":
|
||||||
|
return true;
|
||||||
|
case "suspend":
|
||||||
|
return true;
|
||||||
|
case "timeupdate":
|
||||||
|
return true;
|
||||||
|
case "volumechange":
|
||||||
|
return true;
|
||||||
|
case "waiting":
|
||||||
|
return true;
|
||||||
|
case "animationstart":
|
||||||
|
return true;
|
||||||
|
case "animationend":
|
||||||
|
return true;
|
||||||
|
case "animationiteration":
|
||||||
|
return true;
|
||||||
|
case "transitionend":
|
||||||
|
return true;
|
||||||
|
case "toggle":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use std::any::Any;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dioxus_core::{ElementId, EventPriority, UserEvent};
|
use dioxus_core::{ElementId, EventPriority, UserEvent};
|
||||||
|
use dioxus_html::event_bubbles;
|
||||||
use dioxus_html::on::*;
|
use dioxus_html::on::*;
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
@ -46,6 +47,7 @@ pub fn trigger_from_serialized(val: serde_json::Value) -> UserEvent {
|
||||||
scope_id: None,
|
scope_id: None,
|
||||||
element: mounted_dom_id,
|
element: mounted_dom_id,
|
||||||
data: event,
|
data: event,
|
||||||
|
bubbles: event_bubbles(name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use dioxus_html::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, S
|
||||||
use dioxus_html::input_data::keyboard_types::Modifiers;
|
use dioxus_html::input_data::keyboard_types::Modifiers;
|
||||||
use dioxus_html::input_data::MouseButtonSet as DioxusMouseButtons;
|
use dioxus_html::input_data::MouseButtonSet as DioxusMouseButtons;
|
||||||
use dioxus_html::input_data::{MouseButton as DioxusMouseButton, MouseButtonSet};
|
use dioxus_html::input_data::{MouseButton as DioxusMouseButton, MouseButtonSet};
|
||||||
use dioxus_html::{on::*, KeyCode};
|
use dioxus_html::{event_bubbles, on::*, KeyCode};
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
cell::{RefCell, RefMut},
|
cell::{RefCell, RefMut},
|
||||||
|
@ -187,6 +187,7 @@ impl InnerInputState {
|
||||||
name: "focus",
|
name: "focus",
|
||||||
element: Some(id),
|
element: Some(id),
|
||||||
data: Arc::new(FocusData {}),
|
data: Arc::new(FocusData {}),
|
||||||
|
bubbles: event_bubbles("focus"),
|
||||||
});
|
});
|
||||||
resolved_events.push(UserEvent {
|
resolved_events.push(UserEvent {
|
||||||
scope_id: None,
|
scope_id: None,
|
||||||
|
@ -194,6 +195,7 @@ impl InnerInputState {
|
||||||
name: "focusin",
|
name: "focusin",
|
||||||
element: Some(id),
|
element: Some(id),
|
||||||
data: Arc::new(FocusData {}),
|
data: Arc::new(FocusData {}),
|
||||||
|
bubbles: event_bubbles("focusin"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(id) = old_focus {
|
if let Some(id) = old_focus {
|
||||||
|
@ -203,6 +205,7 @@ impl InnerInputState {
|
||||||
name: "focusout",
|
name: "focusout",
|
||||||
element: Some(id),
|
element: Some(id),
|
||||||
data: Arc::new(FocusData {}),
|
data: Arc::new(FocusData {}),
|
||||||
|
bubbles: event_bubbles("focusout"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,6 +251,7 @@ impl InnerInputState {
|
||||||
name,
|
name,
|
||||||
element: Some(node.id),
|
element: Some(node.id),
|
||||||
data,
|
data,
|
||||||
|
bubbles: event_bubbles(name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,6 +653,7 @@ impl RinkInputHandler {
|
||||||
name: event,
|
name: event,
|
||||||
element: Some(node.id),
|
element: Some(node.id),
|
||||||
data: data.clone(),
|
data: data.clone(),
|
||||||
|
bubbles: event_bubbles(event),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
//! - Partial delegation?>
|
//! - Partial delegation?>
|
||||||
|
|
||||||
use dioxus_core::{DomEdit, ElementId, SchedulerMsg, UserEvent};
|
use dioxus_core::{DomEdit, ElementId, SchedulerMsg, UserEvent};
|
||||||
|
use dioxus_html::event_bubbles;
|
||||||
use dioxus_interpreter_js::Interpreter;
|
use dioxus_interpreter_js::Interpreter;
|
||||||
use js_sys::Function;
|
use js_sys::Function;
|
||||||
use std::{any::Any, rc::Rc, sync::Arc};
|
use std::{any::Any, rc::Rc, sync::Arc};
|
||||||
|
@ -45,6 +46,7 @@ impl WebsysDom {
|
||||||
element: Some(ElementId(id)),
|
element: Some(ElementId(id)),
|
||||||
scope_id: None,
|
scope_id: None,
|
||||||
priority: dioxus_core::EventPriority::Medium,
|
priority: dioxus_core::EventPriority::Medium,
|
||||||
|
bubbles: event.bubbles(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(Err(e)) => {
|
Some(Err(e)) => {
|
||||||
|
@ -64,6 +66,7 @@ impl WebsysDom {
|
||||||
element: None,
|
element: None,
|
||||||
scope_id: None,
|
scope_id: None,
|
||||||
priority: dioxus_core::EventPriority::Low,
|
priority: dioxus_core::EventPriority::Low,
|
||||||
|
bubbles: event.bubbles(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,12 +124,17 @@ impl WebsysDom {
|
||||||
event_name, root, ..
|
event_name, root, ..
|
||||||
} => {
|
} => {
|
||||||
let handler: &Function = self.handler.as_ref().unchecked_ref();
|
let handler: &Function = self.handler.as_ref().unchecked_ref();
|
||||||
self.interpreter.NewEventListener(event_name, root, handler);
|
self.interpreter.NewEventListener(
|
||||||
|
event_name,
|
||||||
|
root,
|
||||||
|
handler,
|
||||||
|
event_bubbles(event_name),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DomEdit::RemoveEventListener { root, event } => {
|
DomEdit::RemoveEventListener { root, event } => self
|
||||||
self.interpreter.RemoveEventListener(root, event)
|
.interpreter
|
||||||
}
|
.RemoveEventListener(root, event, event_bubbles(event)),
|
||||||
|
|
||||||
DomEdit::RemoveAttribute { root, name, ns } => {
|
DomEdit::RemoveAttribute { root, name, ns } => {
|
||||||
self.interpreter.RemoveAttribute(root, name, ns)
|
self.interpreter.RemoveAttribute(root, name, ns)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::dom::WebsysDom;
|
use crate::dom::WebsysDom;
|
||||||
use dioxus_core::{VNode, VirtualDom};
|
use dioxus_core::{VNode, VirtualDom};
|
||||||
|
use dioxus_html::event_bubbles;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use web_sys::{Comment, Element, Node, Text};
|
use web_sys::{Comment, Element, Node, Text};
|
||||||
|
|
||||||
|
@ -111,6 +112,7 @@ impl WebsysDom {
|
||||||
listener.event,
|
listener.event,
|
||||||
listener.mounted_node.get().unwrap().as_u64(),
|
listener.mounted_node.get().unwrap().as_u64(),
|
||||||
self.handler.as_ref().unchecked_ref(),
|
self.handler.as_ref().unchecked_ref(),
|
||||||
|
event_bubbles(listener.event),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue