@dualbox/editor 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/js/src/GraphEditor.js +159 -0
  2. package/js/src/c/GraphController.js +646 -0
  3. package/js/src/libs/CodeMirror.js +8 -0
  4. package/js/src/libs/fontawesome.js +1 -0
  5. package/js/src/libs/jsoneditor.css +2 -0
  6. package/js/src/libs/jsoneditor.js +4 -0
  7. package/js/src/m/DualboxUtils.js +35 -0
  8. package/js/src/m/GraphModel.js +2167 -0
  9. package/js/src/m/History.js +94 -0
  10. package/js/src/m/Merger.js +357 -0
  11. package/js/src/v/AppManager.js +61 -0
  12. package/js/src/v/CanvasSizeHandler.js +136 -0
  13. package/js/src/v/ContextMenu.css +45 -0
  14. package/js/src/v/ContextMenu.js +239 -0
  15. package/js/src/v/GraphView.js +928 -0
  16. package/js/src/v/PlumbStyle.js +254 -0
  17. package/js/src/v/Selector.js +239 -0
  18. package/js/src/v/TemplateManager.js +79 -0
  19. package/js/src/v/Translater.js +174 -0
  20. package/js/src/v/Utils.js +7 -0
  21. package/js/src/v/Zoomer.js +201 -0
  22. package/js/src/v/templates/addNode.css +45 -0
  23. package/js/src/v/templates/addNode.html +62 -0
  24. package/js/src/v/templates/addNode.js +34 -0
  25. package/js/src/v/templates/debugNodeInfos.css +5 -0
  26. package/js/src/v/templates/debugNodeInfos.html +336 -0
  27. package/js/src/v/templates/debugNodeInfos.js +31 -0
  28. package/js/src/v/templates/editMainSettings.css +67 -0
  29. package/js/src/v/templates/editMainSettings.html +265 -0
  30. package/js/src/v/templates/editMainSettings.js +240 -0
  31. package/js/src/v/templates/editNodeSettings.css +86 -0
  32. package/js/src/v/templates/editNodeSettings.html +539 -0
  33. package/js/src/v/templates/editNodeSettings.js +356 -0
  34. package/js/src/v/templates/graphNode.css +333 -0
  35. package/js/src/v/templates/graphNode.html +227 -0
  36. package/js/src/v/templates/graphNode.js +412 -0
  37. package/js/src/v/templates/main.css +353 -0
  38. package/js/src/v/templates/main.html +149 -0
  39. package/js/src/v/templates/main.js +511 -0
  40. package/js/src/v/templates/searchResults.css +50 -0
  41. package/js/src/v/templates/searchResults.html +46 -0
  42. package/js/src/v/templates/searchResults.js +176 -0
  43. package/package.json +3 -2
@@ -0,0 +1,239 @@
1
+ require('./ContextMenu.css');
2
+
3
+ const instances = [];
4
+ let mdCoord = null;
5
+ let nextId = 0;
6
+
7
+ // Tiny polyfill for Element.matches() for IE
8
+ if (!Element.prototype.matches) {
9
+ Element.prototype.matches = Element.prototype.msMatchesSelector;
10
+ }
11
+
12
+ // Gets an element's next/previous sibling that matches the given selector
13
+ function getSibling(el, selector, direction = 1) {
14
+ const sibling = direction > 0 ? el.nextElementSibling : el.previousElementSibling;
15
+ if (!sibling || sibling.matches(selector)) {
16
+ return sibling;
17
+ }
18
+ return getSibling(sibling, selector, direction);
19
+ }
20
+
21
+ // Fires custom event on given element
22
+ function emit(el, type, data = {}) {
23
+ const event = document.createEvent('Event');
24
+
25
+ Object.keys(data).forEach((key) => {
26
+ event[key] = data[key];
27
+ });
28
+
29
+ event.initEvent(type, true, true);
30
+ el.dispatchEvent(event);
31
+ }
32
+
33
+ class ContextMenu {
34
+ constructor(selector, items, options = {
35
+ className: '',
36
+ minimalStyling: false,
37
+ }) {
38
+ this.selector = selector;
39
+ this.items = items;
40
+ this.options = options;
41
+ this.id = nextId++;
42
+ this.target = null;
43
+
44
+ this.create();
45
+ instances.push(this);
46
+ }
47
+
48
+ // Creates DOM elements, sets up event listeners
49
+ create() {
50
+ // Create root <ul>
51
+ this.menu = document.createElement('ul');
52
+ this.menu.className = 'ContextMenu';
53
+ this.menu.oncontextmenu=function(e) { e.preventDefault(); e.stopPropagation(); return false; }; // don't do anything on right click
54
+ this.menu.setAttribute('data-contextmenu', this.id);
55
+ this.menu.setAttribute('tabindex', -1);
56
+ this.menu.addEventListener('keyup', (e) => {
57
+ switch (e.which) {
58
+ case 38:
59
+ this.moveFocus(-1);
60
+ break;
61
+ case 40:
62
+ this.moveFocus(1);
63
+ break;
64
+ case 27:
65
+ this.hide();
66
+ break;
67
+ default:
68
+ // do nothing
69
+ }
70
+ });
71
+
72
+ if (!this.options.minimalStyling) {
73
+ this.menu.classList.add('ContextMenu--theme-default');
74
+ }
75
+ if (this.options.className) {
76
+ this.options.className.split(' ').forEach(cls => this.menu.classList.add(cls));
77
+ }
78
+
79
+ // Create <li>'s for each menu item
80
+ this.items.forEach((item, index) => {
81
+ const li = document.createElement('li');
82
+
83
+ if (!('name' in item)) {
84
+ // Insert a divider
85
+ li.className = 'ContextMenu-divider';
86
+ } else {
87
+ li.className = 'ContextMenu-item';
88
+ li.textContent = item.name;
89
+ li.setAttribute('data-contextmenuitem', index);
90
+ li.setAttribute('tabindex', 0);
91
+ li.addEventListener('click', this.select.bind(this, li));
92
+ li.addEventListener('keyup', (e) => {
93
+ if (e.which === 13) {
94
+ this.select(li);
95
+ }
96
+ });
97
+ }
98
+
99
+ this.menu.appendChild(li);
100
+ });
101
+
102
+ // Add root element to the <body>
103
+ document.body.appendChild(this.menu);
104
+
105
+ emit(this.menu, 'created');
106
+ }
107
+
108
+ // Shows context menu
109
+ show(e) {
110
+ this.menu.style.left = `${e.pageX}px`;
111
+ this.menu.style.top = `${e.pageY}px`;
112
+ this.menu.classList.add('is-open');
113
+ this.target = e.target;
114
+ // Give context menu focus
115
+ this.menu.focus();
116
+ // Disable native context menu
117
+ e.preventDefault();
118
+
119
+ emit(this.menu, 'shown');
120
+ }
121
+
122
+ // Hides context menu
123
+ hide() {
124
+ this.menu.classList.remove('is-open');
125
+ this.target = null;
126
+ emit(this.menu, 'hidden');
127
+ }
128
+
129
+ // Selects the given item and calls its handler
130
+ select(item) {
131
+ const itemId = item.getAttribute('data-contextmenuitem');
132
+ if (this.items[itemId]) {
133
+ // Call item handler with target element as parameter
134
+ this.items[itemId].fn(this.target);
135
+ }
136
+ this.hide();
137
+ emit(this.menu, 'itemselected');
138
+ }
139
+
140
+ // Moves focus to the next/previous menu item
141
+ moveFocus(direction = 1) {
142
+ const focused = this.menu.querySelector('[data-contextmenuitem]:focus');
143
+ let next;
144
+
145
+ if (focused) {
146
+ next = getSibling(focused, '[data-contextmenuitem]', direction);
147
+ }
148
+
149
+ if (!next) {
150
+ next = direction > 0
151
+ ? this.menu.querySelector('[data-contextmenuitem]:first-child')
152
+ : this.menu.querySelector('[data-contextmenuitem]:last-child');
153
+ }
154
+
155
+ if (next) next.focus();
156
+ }
157
+
158
+ // Convenience method for adding an event listener
159
+ on(type, fn) {
160
+ this.menu.addEventListener(type, fn);
161
+ }
162
+
163
+ // Convenience method for removing an event listener
164
+ off(type, fn) {
165
+ this.menu.removeEventListener(type, fn);
166
+ }
167
+
168
+ // Removes DOM elements, stop listeners
169
+ destroy() {
170
+ this.menu.parentElement.removeChild(this.menu);
171
+ this.menu = null;
172
+ instances.splice(instances.indexOf(this), 1);
173
+ }
174
+
175
+ static initialize() {
176
+ document.addEventListener('contextmenu', (e) => {
177
+ // unbind browser contextmenu
178
+ e.preventDefault();
179
+ e.stopPropagation();
180
+ });
181
+
182
+ document.addEventListener('mousedown', (e) => {
183
+ if( e.which === 3 ) { // right click
184
+ mdCoord = {
185
+ "x": e.pageX,
186
+ "y": e.pageY
187
+ };
188
+ }
189
+ });
190
+
191
+ // Listen for contextmenu event to show menu
192
+ document.addEventListener('mouseup', (e) => {
193
+ if( e.which === 3 && mdCoord !== null ) {
194
+ // if the mouse didnt move much since the mouse down, we show the context menu
195
+ var diff = Math.abs(e.pageX - mdCoord.x) + Math.abs(e.pageY -mdCoord.y);
196
+ if( diff < 4 ) {
197
+ var target = $(e.target);
198
+ if( $(target).closest('.jsplumb-endpoint-anchor').length !== 0 ) target = $(target).closest('.jsplumb-endpoint-anchor');
199
+
200
+ instances.forEach((menu) => {
201
+ if( target[0].matches(menu.selector) ||
202
+ target[0].closest('.card') &&
203
+ target[0].closest('.card').matches(menu.selector) ) {
204
+ menu.show(e);
205
+
206
+ /*
207
+ e.preventDefault();
208
+ e.stopPropagation();
209
+ e.stopImmediatePropagation();
210
+ */
211
+ return false;
212
+ }
213
+ });
214
+ }
215
+
216
+ mdCoord = null; // reset mdCoord
217
+ }
218
+ });
219
+
220
+ // Listen for click event to hide menu
221
+ document.addEventListener('click', (e) => {
222
+ instances.forEach((menu) => {
223
+ if (!e.target.matches(`[data-contextmenu="${menu.id}"], [data-contextmenu="${menu.id}"] *`)) {
224
+ menu.hide();
225
+ }
226
+ });
227
+ });
228
+ }
229
+
230
+ static clean() {
231
+ instances.forEach((menu) => {
232
+ menu.destroy();
233
+ });
234
+ }
235
+ }
236
+
237
+
238
+
239
+ module.exports = ContextMenu;