Skip to content
This repository was archived by the owner on Nov 6, 2019. It is now read-only.

Commit c5b6e38

Browse files
committed
contextEvent is now a property of CommandRegistry
1 parent 57a76ca commit c5b6e38

File tree

2 files changed

+99
-2
lines changed

2 files changed

+99
-2
lines changed

packages/commands/src/index.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,72 @@ class CommandRegistry {
8181
return this._keyBindings;
8282
}
8383

84+
get contextEvent(): MouseEvent | null {
85+
return this._contextEvent;
86+
}
87+
88+
set contextEvent(event: MouseEvent | null) {
89+
if (event === null) {
90+
this._contextEvent = null;
91+
this._contextEventCurrentTarget = null;
92+
}
93+
else {
94+
this._contextEvent = event;
95+
// event.currentTarget is nulled when the next event occurs, so record for later
96+
this._contextEventCurrentTarget = event.currentTarget as (Element | null);
97+
}
98+
}
99+
100+
contextEventTarget(selector: string): Element | null {
101+
// Validate the selector
102+
if (selector.indexOf(',') !== -1) {
103+
throw new Error(`Selector cannot contain commas: ${selector}`);
104+
}
105+
if (!Selector.isValid(selector)) {
106+
throw new Error(`Invalid selector: ${selector}`);
107+
}
108+
109+
let event = this._contextEvent;
110+
let currentTarget = this._contextEventCurrentTarget;
111+
if (!event || !currentTarget) {
112+
return null;
113+
}
114+
115+
// Look up the target of the event.
116+
let target = event.target as (Element | null);
117+
118+
// Bail if there is no target.
119+
if (!target) {
120+
return null;
121+
}
122+
123+
// There are some third party libraries that cause the `target` to
124+
// be detached from the DOM before Phosphor can process the event.
125+
if (!currentTarget.contains(target)) {
126+
target = document.elementFromPoint(event.clientX, event.clientY);
127+
if (!target || !currentTarget.contains(target)) {
128+
return null;
129+
}
130+
}
131+
132+
while (target !== null) {
133+
// Return the first Element that matches the selector
134+
if (Selector.matches(target, selector)) {
135+
return target;
136+
}
137+
138+
// Stop searching at the limits of the DOM range.
139+
if (target === currentTarget) {
140+
return null;
141+
}
142+
143+
// Step to the parent DOM level.
144+
target = target.parentElement;
145+
}
146+
147+
return null;
148+
}
149+
84150
/**
85151
* List the ids of the registered commands.
86152
*
@@ -565,6 +631,8 @@ class CommandRegistry {
565631
private _commandChanged = new Signal<this, CommandRegistry.ICommandChangedArgs>(this);
566632
private _commandExecuted = new Signal<this, CommandRegistry.ICommandExecutedArgs>(this);
567633
private _keyBindingChanged = new Signal<this, CommandRegistry.IKeyBindingChangedArgs>(this);
634+
private _contextEvent: MouseEvent | null = null;
635+
private _contextEventCurrentTarget: Element | null = null;
568636
}
569637

570638

packages/widgets/src/contextmenu.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,32 @@ import {
2525
Menu
2626
} from './menu';
2727

28+
import {
29+
Message
30+
} from '@phosphor/messaging';
31+
32+
export
33+
class MenuForContextMenu extends Menu {
34+
triggerActiveItem(): void {
35+
this._doCleanupContextEvent = false;
36+
super.triggerActiveItem();
37+
this._cleanupContextEvent();
38+
this._doCleanupContextEvent = true;
39+
}
40+
41+
protected onCloseRequest(msg: Message): void {
42+
super.onCloseRequest(msg);
43+
if (this._doCleanupContextEvent) {
44+
this._cleanupContextEvent();
45+
}
46+
}
47+
48+
private _cleanupContextEvent(): void {
49+
this.commands.contextEvent = null;
50+
}
51+
52+
private _doCleanupContextEvent: boolean = true;
53+
}
2854

2955
/**
3056
* An object which implements a universal context menu.
@@ -43,13 +69,13 @@ class ContextMenu {
4369
* @param options - The options for initializing the menu.
4470
*/
4571
constructor(options: ContextMenu.IOptions) {
46-
this.menu = new Menu(options);
72+
this.menu = new MenuForContextMenu(options);
4773
}
4874

4975
/**
5076
* The menu widget which displays the matched context items.
5177
*/
52-
readonly menu: Menu;
78+
readonly menu: MenuForContextMenu;
5379

5480
/**
5581
* Add an item to the context menu.
@@ -101,6 +127,9 @@ class ContextMenu {
101127
return false;
102128
}
103129

130+
// Record the initiating event for use in commands
131+
this.menu.commands.contextEvent = event;
132+
104133
// Add the filtered items to the menu.
105134
each(items, item => { this.menu.addItem(item); });
106135

0 commit comments

Comments
 (0)