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

Commit

Permalink
the target of a context menu item is now passed as a third optional a…
Browse files Browse the repository at this point in the history
…rg to `execute`
  • Loading branch information
telamonian committed Aug 19, 2018
1 parent 6a85cdd commit c1d517b
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 28 deletions.
16 changes: 12 additions & 4 deletions packages/commands/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,13 +335,16 @@ class CommandRegistry {
*
* @param args - The arguments for the command.
*
* @param target - (optional) The HTML node on which this command
* was invoked.
*
* @returns A promise which resolves with the result of the command.
*
* #### Notes
* The promise will reject if the command throws an exception,
* or if the command is not registered.
*/
execute(id: string, args: ReadonlyJSONObject = JSONExt.emptyObject): Promise<any> {
execute(id: string, args: ReadonlyJSONObject = JSONExt.emptyObject, target?: HTMLElement): Promise<any> {
// Reject if the command is not registered.
let cmd = this._commands[id];
if (!cmd) {
Expand All @@ -351,7 +354,7 @@ class CommandRegistry {
// Execute the command and reject if an exception is thrown.
let value: any;
try {
value = cmd.execute.call(undefined, args);
value = cmd.execute.call(undefined, args, target);
} catch (err) {
value = Promise.reject(err);
}
Expand All @@ -360,7 +363,7 @@ class CommandRegistry {
let result = Promise.resolve(value);

// Emit the command executed signal.
this._commandExecuted.emit({ id, args, result });
this._commandExecuted.emit({ id, args, target, result });

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

/**
* A type alias for a simple immutable string dataset.
Expand Down Expand Up @@ -804,6 +807,11 @@ namespace CommandRegistry {
*/
readonly args: ReadonlyJSONObject;

/**
* The HTML node on which the command was invoked.
*/
readonly target?: HTMLElement;

/**
* The promise which resolves with the result of the command.
*/
Expand Down
26 changes: 3 additions & 23 deletions packages/widgets/src/contextmenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,18 +167,6 @@ namespace ContextMenu {
* The default rank is `Infinity`.
*/
rank?: number;

/**
* Pass a selected node's dataset to an item's command.
*
* If this flag is set, when a contextmenu item is matched
* to the target of a contextmenu event, the key-value pairs
* in `target.dataset` (if present) will be added as
* properties of `item.args`.
*
* Only meaningful for items of type `command`.
*/
passDataset?: boolean;
}
}

Expand All @@ -202,11 +190,6 @@ namespace Private {
*/
rank: number;

/**
* Pass a selected node's dataset to an item's command.
*/
passDataset: boolean;

/**
* The tie-breaking id for the item.
*/
Expand All @@ -220,8 +203,7 @@ namespace Private {
function createItem(options: ContextMenu.IItemOptions, id: number): IItem {
let selector = validateSelector(options.selector);
let rank = options.rank !== undefined ? options.rank : Infinity;
let passDataset = options.passDataset !== undefined ? options.passDataset : false;
return { ...options, selector, rank, passDataset, id };
return { ...options, selector, rank, id };
}

/**
Expand Down Expand Up @@ -284,10 +266,8 @@ namespace Private {
continue;
}

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

// Add the matched item to the result for this DOM level.
matches.push(item);
Expand Down
43 changes: 42 additions & 1 deletion packages/widgets/src/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,16 @@ class Menu extends Widget {
return;
}

// item.target is nulled by the .close(), so grab it now
let target = item.target;

// Close the root menu before executing the command.
this.rootMenu.close();

// Execute the command for the item.
let { command, args } = item;
if (this.commands.isEnabled(command, args)) {
this.commands.execute(command, args);
this.commands.execute(command, args, target);
} else {
console.log(`Command '${command}' is disabled.`);
}
Expand Down Expand Up @@ -561,6 +564,11 @@ class Menu extends Widget {
childMenu.close();
}

// Zero out the .target property of every item owned by this menu.
for (let item of this._items) {
item.clearTarget();
}

// Remove this menu from its parent and activate the parent.
let parentMenu = this._parentMenu;
if (parentMenu) {
Expand Down Expand Up @@ -987,6 +995,13 @@ namespace Menu {
*/
args?: ReadonlyJSONObject;

/**
* The HTML node associated with this menu item, if any.
*
* The default value is undefined.
*/
target?: HTMLElement;

/**
* The submenu for a `'submenu'` type item.
*
Expand Down Expand Up @@ -1018,6 +1033,11 @@ namespace Menu {
*/
readonly args: ReadonlyJSONObject;

/**
* The HTML node associated with this menu item, if any.
*/
readonly target?: HTMLElement;

/**
* The submenu for a `'submenu'` type item.
*/
Expand Down Expand Up @@ -1082,6 +1102,11 @@ namespace Menu {
* The key binding for the menu item.
*/
readonly keyBinding: CommandRegistry.IKeyBinding | null;

/**
* Zeros out the .target property.
*/
clearTarget(): void;
}

/**
Expand Down Expand Up @@ -1677,6 +1702,7 @@ namespace Private {
*/
constructor(commands: CommandRegistry, options: Menu.IItemOptions) {
this._commands = commands;
this._target = options.target;
this.type = options.type || 'command';
this.command = options.command || '';
this.args = options.args || JSONExt.emptyObject;
Expand All @@ -1703,6 +1729,13 @@ namespace Private {
*/
readonly submenu: Menu | null;

/**
* The HTML node associated with this menu item, if any.
*/
get target(): HTMLElement | undefined {
return this._target;
}

/**
* The display label for the menu item.
*/
Expand Down Expand Up @@ -1850,6 +1883,14 @@ namespace Private {
return null;
}

/**
* Zeros out the ._target property.
*/
clearTarget(): void {
this._target = undefined;
}

private _commands: CommandRegistry;
private _target?: HTMLElement;
}
}

0 comments on commit c1d517b

Please sign in to comment.