1 | /* -----------------------------------------------------------------------------
|
2 | | Copyright (c) Jupyter Development Team.
|
3 | | Distributed under the terms of the Modified BSD License.
|
4 | |----------------------------------------------------------------------------*/
|
5 | import { JSONExt } from '@lumino/coreutils';
|
6 | /**
|
7 | * The command data attribute added to nodes that are connected.
|
8 | */
|
9 | const COMMAND_ATTR = 'commandlinker-command';
|
10 | /**
|
11 | * The args data attribute added to nodes that are connected.
|
12 | */
|
13 | const ARGS_ATTR = 'commandlinker-args';
|
14 | /**
|
15 | * A static class that provides helper methods to generate clickable nodes that
|
16 | * execute registered commands with pre-populated arguments.
|
17 | */
|
18 | export class CommandLinker {
|
19 | /**
|
20 | * Instantiate a new command linker.
|
21 | */
|
22 | constructor(options) {
|
23 | this._isDisposed = false;
|
24 | this._commands = options.commands;
|
25 | document.body.addEventListener('click', this);
|
26 | }
|
27 | /**
|
28 | * Test whether the linker is disposed.
|
29 | */
|
30 | get isDisposed() {
|
31 | return this._isDisposed;
|
32 | }
|
33 | /**
|
34 | * Dispose of the resources held by the linker.
|
35 | */
|
36 | dispose() {
|
37 | if (this.isDisposed) {
|
38 | return;
|
39 | }
|
40 | this._isDisposed = true;
|
41 | document.body.removeEventListener('click', this);
|
42 | }
|
43 | /**
|
44 | * Connect a command/argument pair to a given node so that when it is clicked,
|
45 | * the command will execute.
|
46 | *
|
47 | * @param node - The node being connected.
|
48 | *
|
49 | * @param command - The command ID to execute upon click.
|
50 | *
|
51 | * @param args - The arguments with which to invoke the command.
|
52 | *
|
53 | * @returns The same node that was passed in, after it has been connected.
|
54 | *
|
55 | * #### Notes
|
56 | * Only `click` events will execute the command on a connected node. So, there
|
57 | * are two considerations that are relevant:
|
58 | * 1. If a node is connected, the default click action will be prevented.
|
59 | * 2. The `HTMLElement` passed in should be clickable.
|
60 | */
|
61 | connectNode(node, command, args) {
|
62 | node.setAttribute(`data-${COMMAND_ATTR}`, command);
|
63 | if (args !== void 0) {
|
64 | node.setAttribute(`data-${ARGS_ATTR}`, JSON.stringify(args));
|
65 | }
|
66 | return node;
|
67 | }
|
68 | /**
|
69 | * Disconnect a node that has been connected to execute a command on click.
|
70 | *
|
71 | * @param node - The node being disconnected.
|
72 | *
|
73 | * @returns The same node that was passed in, after it has been disconnected.
|
74 | *
|
75 | * #### Notes
|
76 | * This method is safe to call multiple times and is safe to call on nodes
|
77 | * that were never connected.
|
78 | *
|
79 | * This method can be called on rendered virtual DOM nodes that were populated
|
80 | * using the `populateVNodeDataset` method in order to disconnect them from
|
81 | * executing their command/argument pair.
|
82 | */
|
83 | disconnectNode(node) {
|
84 | node.removeAttribute(`data-${COMMAND_ATTR}`);
|
85 | node.removeAttribute(`data-${ARGS_ATTR}`);
|
86 | return node;
|
87 | }
|
88 | /**
|
89 | * Handle the DOM events for the command linker helper class.
|
90 | *
|
91 | * @param event - The DOM event sent to the class.
|
92 | *
|
93 | * #### Notes
|
94 | * This method implements the DOM `EventListener` interface and is
|
95 | * called in response to events on the panel's DOM node. It should
|
96 | * not be called directly by user code.
|
97 | */
|
98 | handleEvent(event) {
|
99 | switch (event.type) {
|
100 | case 'click':
|
101 | this._evtClick(event);
|
102 | break;
|
103 | default:
|
104 | return;
|
105 | }
|
106 | }
|
107 | /**
|
108 | * Populate the `dataset` attribute within the collection of attributes used
|
109 | * to instantiate a virtual DOM node with the values necessary for its
|
110 | * rendered DOM node to respond to clicks by executing a command/argument
|
111 | * pair.
|
112 | *
|
113 | * @param command - The command ID to execute upon click.
|
114 | *
|
115 | * @param args - The arguments with which to invoke the command.
|
116 | *
|
117 | * @returns A `dataset` collection for use within virtual node attributes.
|
118 | *
|
119 | * #### Notes
|
120 | * The return value can be used on its own as the value for the `dataset`
|
121 | * attribute of a virtual element, or it can be added to an existing `dataset`
|
122 | * as in the example below.
|
123 | *
|
124 | * #### Example
|
125 | * ```typescript
|
126 | * let command = 'some:command-id';
|
127 | * let args = { alpha: 'beta' };
|
128 | * let anchor = h.a({
|
129 | * className: 'some-class',
|
130 | * dataset: {
|
131 | * foo: '1',
|
132 | * bar: '2',
|
133 | * ../...linker.populateVNodeDataset(command, args)
|
134 | * }
|
135 | * }, 'some text');
|
136 | * ```
|
137 | */
|
138 | populateVNodeDataset(command, args) {
|
139 | let dataset;
|
140 | if (args !== void 0) {
|
141 | dataset = { [ARGS_ATTR]: JSON.stringify(args), [COMMAND_ATTR]: command };
|
142 | }
|
143 | else {
|
144 | dataset = { [COMMAND_ATTR]: command };
|
145 | }
|
146 | return dataset;
|
147 | }
|
148 | /**
|
149 | * The global click handler that deploys commands/argument pairs that are
|
150 | * attached to the node being clicked.
|
151 | */
|
152 | _evtClick(event) {
|
153 | let target = event.target;
|
154 | while (target && target.parentElement) {
|
155 | if (target.hasAttribute(`data-${COMMAND_ATTR}`)) {
|
156 | event.preventDefault();
|
157 | const command = target.getAttribute(`data-${COMMAND_ATTR}`);
|
158 | if (!command) {
|
159 | return;
|
160 | }
|
161 | const argsValue = target.getAttribute(`data-${ARGS_ATTR}`);
|
162 | let args = JSONExt.emptyObject;
|
163 | if (argsValue) {
|
164 | args = JSON.parse(argsValue);
|
165 | }
|
166 | void this._commands.execute(command, args);
|
167 | return;
|
168 | }
|
169 | target = target.parentElement;
|
170 | }
|
171 | }
|
172 | }
|
173 | //# sourceMappingURL=commandlinker.js.map |
\ | No newline at end of file |