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

Commit c1d517b

Browse files
committed
the target of a context menu item is now passed as a third optional arg to execute
1 parent 6a85cdd commit c1d517b

File tree

3 files changed

+57
-28
lines changed

3 files changed

+57
-28
lines changed

packages/commands/src/index.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -335,13 +335,16 @@ class CommandRegistry {
335335
*
336336
* @param args - The arguments for the command.
337337
*
338+
* @param target - (optional) The HTML node on which this command
339+
* was invoked.
340+
*
338341
* @returns A promise which resolves with the result of the command.
339342
*
340343
* #### Notes
341344
* The promise will reject if the command throws an exception,
342345
* or if the command is not registered.
343346
*/
344-
execute(id: string, args: ReadonlyJSONObject = JSONExt.emptyObject): Promise<any> {
347+
execute(id: string, args: ReadonlyJSONObject = JSONExt.emptyObject, target?: HTMLElement): Promise<any> {
345348
// Reject if the command is not registered.
346349
let cmd = this._commands[id];
347350
if (!cmd) {
@@ -351,7 +354,7 @@ class CommandRegistry {
351354
// Execute the command and reject if an exception is thrown.
352355
let value: any;
353356
try {
354-
value = cmd.execute.call(undefined, args);
357+
value = cmd.execute.call(undefined, args, target);
355358
} catch (err) {
356359
value = Promise.reject(err);
357360
}
@@ -360,7 +363,7 @@ class CommandRegistry {
360363
let result = Promise.resolve(value);
361364

362365
// Emit the command executed signal.
363-
this._commandExecuted.emit({ id, args, result });
366+
this._commandExecuted.emit({ id, args, target, result });
364367

365368
// Return the result promise to the caller.
366369
return result;
@@ -577,7 +580,7 @@ namespace CommandRegistry {
577580
* A type alias for a user-defined command function.
578581
*/
579582
export
580-
type CommandFunc<T> = (args: ReadonlyJSONObject) => T;
583+
type CommandFunc<T> = (args: ReadonlyJSONObject, target?: HTMLElement) => T;
581584

582585
/**
583586
* A type alias for a simple immutable string dataset.
@@ -804,6 +807,11 @@ namespace CommandRegistry {
804807
*/
805808
readonly args: ReadonlyJSONObject;
806809

810+
/**
811+
* The HTML node on which the command was invoked.
812+
*/
813+
readonly target?: HTMLElement;
814+
807815
/**
808816
* The promise which resolves with the result of the command.
809817
*/

packages/widgets/src/contextmenu.ts

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -167,18 +167,6 @@ namespace ContextMenu {
167167
* The default rank is `Infinity`.
168168
*/
169169
rank?: number;
170-
171-
/**
172-
* Pass a selected node's dataset to an item's command.
173-
*
174-
* If this flag is set, when a contextmenu item is matched
175-
* to the target of a contextmenu event, the key-value pairs
176-
* in `target.dataset` (if present) will be added as
177-
* properties of `item.args`.
178-
*
179-
* Only meaningful for items of type `command`.
180-
*/
181-
passDataset?: boolean;
182170
}
183171
}
184172

@@ -202,11 +190,6 @@ namespace Private {
202190
*/
203191
rank: number;
204192

205-
/**
206-
* Pass a selected node's dataset to an item's command.
207-
*/
208-
passDataset: boolean;
209-
210193
/**
211194
* The tie-breaking id for the item.
212195
*/
@@ -220,8 +203,7 @@ namespace Private {
220203
function createItem(options: ContextMenu.IItemOptions, id: number): IItem {
221204
let selector = validateSelector(options.selector);
222205
let rank = options.rank !== undefined ? options.rank : Infinity;
223-
let passDataset = options.passDataset !== undefined ? options.passDataset : false;
224-
return { ...options, selector, rank, passDataset, id };
206+
return { ...options, selector, rank, id };
225207
}
226208

227209
/**
@@ -284,10 +266,8 @@ namespace Private {
284266
continue;
285267
}
286268

287-
// Pass the target's dataset to the matched item's args, if requested.
288-
if (item.passDataset && 'dataset' in target) {
289-
item.args = {...item.args, ...(target as any)['dataset']};
290-
}
269+
// Store the target for later use by the matching menu item.
270+
item.target = target as HTMLElement;
291271

292272
// Add the matched item to the result for this DOM level.
293273
matches.push(item);

packages/widgets/src/menu.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,16 @@ class Menu extends Widget {
293293
return;
294294
}
295295

296+
// item.target is nulled by the .close(), so grab it now
297+
let target = item.target;
298+
296299
// Close the root menu before executing the command.
297300
this.rootMenu.close();
298301

299302
// Execute the command for the item.
300303
let { command, args } = item;
301304
if (this.commands.isEnabled(command, args)) {
302-
this.commands.execute(command, args);
305+
this.commands.execute(command, args, target);
303306
} else {
304307
console.log(`Command '${command}' is disabled.`);
305308
}
@@ -561,6 +564,11 @@ class Menu extends Widget {
561564
childMenu.close();
562565
}
563566

567+
// Zero out the .target property of every item owned by this menu.
568+
for (let item of this._items) {
569+
item.clearTarget();
570+
}
571+
564572
// Remove this menu from its parent and activate the parent.
565573
let parentMenu = this._parentMenu;
566574
if (parentMenu) {
@@ -987,6 +995,13 @@ namespace Menu {
987995
*/
988996
args?: ReadonlyJSONObject;
989997

998+
/**
999+
* The HTML node associated with this menu item, if any.
1000+
*
1001+
* The default value is undefined.
1002+
*/
1003+
target?: HTMLElement;
1004+
9901005
/**
9911006
* The submenu for a `'submenu'` type item.
9921007
*
@@ -1018,6 +1033,11 @@ namespace Menu {
10181033
*/
10191034
readonly args: ReadonlyJSONObject;
10201035

1036+
/**
1037+
* The HTML node associated with this menu item, if any.
1038+
*/
1039+
readonly target?: HTMLElement;
1040+
10211041
/**
10221042
* The submenu for a `'submenu'` type item.
10231043
*/
@@ -1082,6 +1102,11 @@ namespace Menu {
10821102
* The key binding for the menu item.
10831103
*/
10841104
readonly keyBinding: CommandRegistry.IKeyBinding | null;
1105+
1106+
/**
1107+
* Zeros out the .target property.
1108+
*/
1109+
clearTarget(): void;
10851110
}
10861111

10871112
/**
@@ -1677,6 +1702,7 @@ namespace Private {
16771702
*/
16781703
constructor(commands: CommandRegistry, options: Menu.IItemOptions) {
16791704
this._commands = commands;
1705+
this._target = options.target;
16801706
this.type = options.type || 'command';
16811707
this.command = options.command || '';
16821708
this.args = options.args || JSONExt.emptyObject;
@@ -1703,6 +1729,13 @@ namespace Private {
17031729
*/
17041730
readonly submenu: Menu | null;
17051731

1732+
/**
1733+
* The HTML node associated with this menu item, if any.
1734+
*/
1735+
get target(): HTMLElement | undefined {
1736+
return this._target;
1737+
}
1738+
17061739
/**
17071740
* The display label for the menu item.
17081741
*/
@@ -1850,6 +1883,14 @@ namespace Private {
18501883
return null;
18511884
}
18521885

1886+
/**
1887+
* Zeros out the ._target property.
1888+
*/
1889+
clearTarget(): void {
1890+
this._target = undefined;
1891+
}
1892+
18531893
private _commands: CommandRegistry;
1894+
private _target?: HTMLElement;
18541895
}
18551896
}

0 commit comments

Comments
 (0)