mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 14:27:40 +00:00
Close context menus on any click outside the menu (#895)
Current: Right click in e.g. `textarea` leaves litegraph context menus open. Proposed: Any click anywhere outside the context menu (or its sub-menus) will close all context menus.
This commit is contained in:
@@ -18,6 +18,8 @@ export class ContextMenu<TValue = unknown> {
|
||||
current_submenu?: ContextMenu<TValue>
|
||||
lock?: boolean
|
||||
|
||||
controller: AbortController = new AbortController()
|
||||
|
||||
/**
|
||||
* @todo Interface for values requires functionality change - currently accepts
|
||||
* an array of strings, functions, objects, nulls, or undefined.
|
||||
@@ -74,23 +76,26 @@ export class ContextMenu<TValue = unknown> {
|
||||
// delay so the mouse up event is not caught by this element
|
||||
}, 100)
|
||||
|
||||
// Close the context menu when a click occurs outside this context menu or its submenus
|
||||
const { signal } = this.controller
|
||||
const eventOptions = { capture: true, signal }
|
||||
|
||||
if (!this.parentMenu) {
|
||||
document.addEventListener("pointerdown", (e) => {
|
||||
if (e.target instanceof Node && !this.containsNode(e.target)) {
|
||||
this.close()
|
||||
}
|
||||
}, eventOptions)
|
||||
}
|
||||
|
||||
// this prevents the default context browser menu to open in case this menu was created when pressing right button
|
||||
root.addEventListener(
|
||||
"pointerup",
|
||||
function (e) {
|
||||
// console.log("pointerevents: ContextMenu up root prevent");
|
||||
e.preventDefault()
|
||||
return true
|
||||
},
|
||||
true,
|
||||
)
|
||||
root.addEventListener("pointerup", e => e.preventDefault(), true)
|
||||
|
||||
// Right button
|
||||
root.addEventListener(
|
||||
"contextmenu",
|
||||
function (e) {
|
||||
// right button
|
||||
if (e.button != 2) return false
|
||||
e.preventDefault()
|
||||
return false
|
||||
(e) => {
|
||||
if (e.button === 2) e.preventDefault()
|
||||
},
|
||||
true,
|
||||
)
|
||||
@@ -98,11 +103,9 @@ export class ContextMenu<TValue = unknown> {
|
||||
root.addEventListener(
|
||||
"pointerdown",
|
||||
(e) => {
|
||||
// console.log("pointerevents: ContextMenu down");
|
||||
if (e.button == 2) {
|
||||
this.close()
|
||||
e.preventDefault()
|
||||
return true
|
||||
}
|
||||
},
|
||||
true,
|
||||
@@ -179,6 +182,19 @@ export class ContextMenu<TValue = unknown> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if {@link node} is inside this context menu or any of its submenus
|
||||
* @param node The {@link Node} to check
|
||||
* @param visited A set of visited menus to avoid circular references
|
||||
* @returns `true` if {@link node} is inside this context menu or any of its submenus
|
||||
*/
|
||||
containsNode(node: Node, visited: Set<this> = new Set()): boolean {
|
||||
if (visited.has(this)) return false
|
||||
visited.add(this)
|
||||
|
||||
return this.current_submenu?.containsNode(node, visited) || this.root.contains(node)
|
||||
}
|
||||
|
||||
addItem(
|
||||
name: string | null,
|
||||
value: string | IContextMenuValue<TValue> | null,
|
||||
@@ -315,6 +331,7 @@ export class ContextMenu<TValue = unknown> {
|
||||
}
|
||||
|
||||
close(e?: MouseEvent, ignore_parent_menu?: boolean): void {
|
||||
this.controller.abort()
|
||||
this.root.remove()
|
||||
if (this.parentMenu && !ignore_parent_menu) {
|
||||
this.parentMenu.lock = false
|
||||
@@ -343,8 +360,6 @@ export class ContextMenu<TValue = unknown> {
|
||||
const evt = document.createEvent("CustomEvent")
|
||||
evt.initCustomEvent(event_name, true, true, params)
|
||||
if (element.dispatchEvent) element.dispatchEvent(evt)
|
||||
// @ts-expect-error
|
||||
else if (element.__events) element.__events.dispatchEvent(evt)
|
||||
// else nothing seems binded here so nothing to do
|
||||
return evt
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user