@jinntec/fore 3.3.1 → 4.0.0
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.
- package/README.md +98 -70
- package/dist/fore-dev.js +5593 -6832
- package/dist/fore.js +5602 -4887
- package/index.js +5 -10
- package/package.json +7 -7
- package/resources/fore.css +33 -0
- package/src/DependencyNotifyingDomFacade.js +90 -21
- package/src/DependentXPathQueries.js +15 -2
- package/src/ForeElementMixin.js +110 -16
- package/src/UndoManager.js +267 -0
- package/src/actions/abstract-action.js +71 -30
- package/src/actions/fx-action.js +5 -0
- package/src/actions/fx-append.js +3 -3
- package/src/actions/fx-commit-history.js +26 -0
- package/src/actions/fx-hide.js +1 -1
- package/src/actions/fx-insert.js +25 -22
- package/src/actions/fx-load.js +5 -5
- package/src/actions/fx-redo.js +58 -0
- package/src/actions/fx-refresh.js +2 -2
- package/src/actions/fx-reload.js +1 -1
- package/src/actions/fx-replace.js +1 -1
- package/src/actions/fx-send.js +27 -5
- package/src/actions/fx-setattribute.js +11 -7
- package/src/actions/fx-undo.js +58 -0
- package/src/createNodes.js +314 -0
- package/src/fore.js +53 -18
- package/src/functions/fx-functionlib.js +10 -10
- package/src/fx-bind.js +30 -18
- package/src/fx-fore.js +222 -200
- package/src/fx-instance.js +18 -1
- package/src/fx-model.js +236 -69
- package/src/fx-submission.js +37 -29
- package/src/fx-var.js +49 -13
- package/src/getInScopeContext.js +1 -1
- package/src/json/JSONDomFacade.js +1 -1
- package/src/json/JSONLens.js +2 -2
- package/src/ui/UIElement.js +18 -8
- package/src/ui/abstract-control.js +45 -3
- package/src/ui/fx-alert.js +4 -0
- package/src/ui/fx-case.js +1 -1
- package/src/ui/fx-container.js +3 -0
- package/src/ui/fx-control-menu.js +79 -11
- package/src/ui/fx-control.js +130 -41
- package/src/ui/fx-dialog.js +5 -0
- package/src/ui/fx-items.js +6 -6
- package/src/ui/fx-output.js +37 -1
- package/src/ui/fx-repeat.js +1065 -103
- package/src/ui/fx-repeatitem.js +4 -1
- package/src/ui/fx-switch.js +116 -3
- package/src/ui/fx-trigger.js +9 -4
- package/src/ui/fx-upload.js +10 -4
- package/src/ui/repeat-base.js +20 -12
- package/src/withDraggability.js +10 -1
- package/src/xpath-evaluation.js +30 -18
- package/src/xpath-path.js +122 -0
- package/src/xpath-util.js +11 -126
- package/src/actions/StringTpl.js +0 -17
- package/src/extract-predicate-deps.js +0 -57
- package/src/extractPredicateDependencies.js +0 -36
- package/src/json/lensFromNode.js +0 -5
- package/src/json-util.js +0 -27
- package/src/tools/adi.js +0 -1111
- package/src/tools/deprecation.md +0 -1
- package/src/tools/fx-action-log.js +0 -745
- package/src/tools/fx-devtools.js +0 -444
- package/src/tools/fx-dom-inspector.js +0 -610
- package/src/tools/fx-json-instance.js +0 -444
- package/src/tools/fx-log-item.js +0 -128
- package/src/tools/fx-log-settings.js +0 -533
- package/src/tools/fx-minimap.js +0 -203
- package/src/tools/helpers.js +0 -132
- package/src/ui/TemplateExpression.js +0 -12
- package/src/ui/fx-dom-inspector.js +0 -1255
package/src/tools/adi.js
DELETED
|
@@ -1,1111 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addClass,
|
|
3
|
-
removeClass,
|
|
4
|
-
isEmptyTextNode,
|
|
5
|
-
containsOnlyText,
|
|
6
|
-
newElement,
|
|
7
|
-
drawOptions,
|
|
8
|
-
pauseEvent,
|
|
9
|
-
drawAttrRow,
|
|
10
|
-
} from './helpers.js';
|
|
11
|
-
|
|
12
|
-
import { Fore } from '../fore.js';
|
|
13
|
-
|
|
14
|
-
function isAttributeShown(name, sourceNode) {
|
|
15
|
-
if (name === 'style') return false;
|
|
16
|
-
return true;
|
|
17
|
-
// return name === 'id' || name === 'ref' || name === 'event';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class ADI {
|
|
21
|
-
constructor(rootElement, instance) {
|
|
22
|
-
this.sourceNodeByInspectorNodeLookup = new Map();
|
|
23
|
-
|
|
24
|
-
this.uiView = null;
|
|
25
|
-
this.menuView = null;
|
|
26
|
-
this.domView = null;
|
|
27
|
-
this.attrView = null;
|
|
28
|
-
this.optsView = null;
|
|
29
|
-
/**
|
|
30
|
-
* The current active element. Note this is the element in the DOM view
|
|
31
|
-
*/
|
|
32
|
-
this.activeElement = null;
|
|
33
|
-
this.vertResizing = false;
|
|
34
|
-
this.horizResizing = false;
|
|
35
|
-
this.pathScrolling = null;
|
|
36
|
-
this.elemLookup = false;
|
|
37
|
-
this.styleBackup = '';
|
|
38
|
-
this.xPos = 0;
|
|
39
|
-
this.delegatedEvents = [];
|
|
40
|
-
|
|
41
|
-
this.options = {
|
|
42
|
-
align: 'right', // NOTE: left is not supported in this version
|
|
43
|
-
split: 50,
|
|
44
|
-
minSplit: 30,
|
|
45
|
-
visible: true,
|
|
46
|
-
saving: false,
|
|
47
|
-
transparent: true,
|
|
48
|
-
omitEmptyText: true,
|
|
49
|
-
makeVisible: true,
|
|
50
|
-
foldText: true,
|
|
51
|
-
nodeTypes: [Node.ELEMENT_NODE, Node.TEXT_NODE, Node.COMMENT_NODE, Node.DOCUMENT_NODE],
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
if (instance === '#document') {
|
|
55
|
-
this.instanceId = '#document';
|
|
56
|
-
this.document = window.document;
|
|
57
|
-
this.isInstanceViewer = false;
|
|
58
|
-
} else {
|
|
59
|
-
this.instanceId = instance.id;
|
|
60
|
-
if (!instance || instance.localName !== 'fx-instance') {
|
|
61
|
-
console.error('No instance found!');
|
|
62
|
-
}
|
|
63
|
-
this.document = instance.getInstanceData();
|
|
64
|
-
this.isInstanceViewer = true;
|
|
65
|
-
this.options.foldText = false;
|
|
66
|
-
}
|
|
67
|
-
this.drawUI(rootElement);
|
|
68
|
-
this.registerEvents();
|
|
69
|
-
|
|
70
|
-
// We're updating here, but we're doing that again later, when the UI is read (the 'ready' event fires)
|
|
71
|
-
this.drawDOM(this.document, this.domView.querySelector('.adi-tree-view'), true);
|
|
72
|
-
document.addEventListener('execute-action', e => this.processExecuteAction);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Returns selected element or null
|
|
76
|
-
getSelected() {
|
|
77
|
-
if (!this.activeElement) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let elem = document;
|
|
82
|
-
|
|
83
|
-
elem = this.sourceNodeByInspectorNodeLookup.get(this.activeElement);
|
|
84
|
-
/*
|
|
85
|
-
document.dispatchEvent(
|
|
86
|
-
new CustomEvent('path-touched', {
|
|
87
|
-
composed: true,
|
|
88
|
-
bubbles: true,
|
|
89
|
-
detail: {path: elem.modelItem.path},
|
|
90
|
-
}),
|
|
91
|
-
);
|
|
92
|
-
*/
|
|
93
|
-
|
|
94
|
-
return elem;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Loads user defined options stored in HTML5 storage (if available)
|
|
98
|
-
loadOptions() {
|
|
99
|
-
let userOptions = {};
|
|
100
|
-
|
|
101
|
-
userOptions = JSON.parse(window.localStorage.getItem('ADI.options')) || {};
|
|
102
|
-
|
|
103
|
-
// merge with defaults
|
|
104
|
-
for (const opt of Object.keys(userOptions)) {
|
|
105
|
-
this.options[opt] = userOptions[opt];
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Saves user defined options into the HTML5 storage (if available)
|
|
110
|
-
saveOptions() {
|
|
111
|
-
if (this.options.saving) {
|
|
112
|
-
window.localStorage.setItem('ADI.options', JSON.stringify(this.options));
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Checks if a node has some child nodes and if at least on of them is of a supported type
|
|
117
|
-
hasRequiredNodes(node) {
|
|
118
|
-
if (typeof node !== 'object') {
|
|
119
|
-
throw new Error(
|
|
120
|
-
`hasRequiredNodes: Expected argument node of type object, ${typeof node} given.`,
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (node.hasChildNodes()) {
|
|
125
|
-
for (let i = 0, len = node.childNodes.length; i < len; i += 1) {
|
|
126
|
-
const child = node.childNodes[i];
|
|
127
|
-
if (this.options.nodeTypes.includes(child.nodeType)) {
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Creates a starting markup for a new DOM tree view node
|
|
137
|
-
newTreeNode(sourceNode) {
|
|
138
|
-
if (typeof sourceNode !== 'object') {
|
|
139
|
-
throw new Error(
|
|
140
|
-
`newTreeNode: Expected argument node of type object, ${typeof sourceNode} given.`,
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const withChildren = this.hasRequiredNodes(sourceNode);
|
|
145
|
-
let omit = false;
|
|
146
|
-
let adiNode = sourceNode.nodeName.startsWith('FX-')
|
|
147
|
-
? `adi-node ${sourceNode.nodeName.toLowerCase()}`
|
|
148
|
-
: '';
|
|
149
|
-
if (sourceNode.nodeName.startsWith('FX-')) {
|
|
150
|
-
adiNode = `adi-node ${sourceNode.nodeName.toLowerCase()}`;
|
|
151
|
-
adiNode += Fore.isActionElement(sourceNode.nodeName) ? ' action' : '';
|
|
152
|
-
}
|
|
153
|
-
const elem = newElement('li', {
|
|
154
|
-
class: adiNode,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// do not show ADI DOM nodes in the DOM view
|
|
158
|
-
if (sourceNode === this.uiView) {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// generate UI for elements with children
|
|
163
|
-
if (withChildren) {
|
|
164
|
-
elem.appendChild(newElement('span', { class: 'adi-trigger' }));
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// we can omit empty text nodes if allowed in options
|
|
168
|
-
if (this.options.omitEmptyText && sourceNode.nodeType === Node.TEXT_NODE) {
|
|
169
|
-
omit = isEmptyTextNode(sourceNode);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (!omit) {
|
|
173
|
-
const tagStart = newElement('span');
|
|
174
|
-
|
|
175
|
-
this.sourceNodeByInspectorNodeLookup.set(tagStart, sourceNode);
|
|
176
|
-
this.sourceNodeByInspectorNodeLookup.set(sourceNode, tagStart);
|
|
177
|
-
|
|
178
|
-
let tagEnd = null;
|
|
179
|
-
|
|
180
|
-
if (containsOnlyText(sourceNode)) {
|
|
181
|
-
if (sourceNode.nodeType === Node.COMMENT_NODE) {
|
|
182
|
-
addClass(tagStart, 'adi-comment-node');
|
|
183
|
-
if (typeof tagStart.innerText === 'string') {
|
|
184
|
-
tagStart.innerText = `<!-- ${sourceNode.textContent} -->`;
|
|
185
|
-
}
|
|
186
|
-
} else {
|
|
187
|
-
addClass(tagStart, 'adi-text-node');
|
|
188
|
-
tagStart.textContent = sourceNode.textContent;
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
addClass(tagStart, 'adi-normal-node');
|
|
192
|
-
if (sourceNode.nodeType !== Node.DOCUMENT_NODE) {
|
|
193
|
-
// tagStart.textContent = '<' + node.nodeName.toLowerCase() + '>';
|
|
194
|
-
|
|
195
|
-
/*
|
|
196
|
-
let attrString = `<${sourceNode.nodeName.toLowerCase()} `;
|
|
197
|
-
if(sourceNode.attributes){
|
|
198
|
-
Array.from(sourceNode.attributes).forEach(attr => {
|
|
199
|
-
attrString += `${attr.nodeName}="${attr.nodeValue}" `;
|
|
200
|
-
});
|
|
201
|
-
console.log('ATTRSTRING',attrString);
|
|
202
|
-
}
|
|
203
|
-
if (sourceNode.nodeName === 'FX-BIND') {
|
|
204
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()} ref="${sourceNode.getAttribute('ref')}">`;
|
|
205
|
-
} else if (sourceNode.nodeName === 'FX-INSERT') {
|
|
206
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()} ref="${sourceNode.getAttribute('ref')}">`;
|
|
207
|
-
} else if (sourceNode.nodeName === 'FX-INSTANCE') {
|
|
208
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()} id="${sourceNode.id}">`;
|
|
209
|
-
} else if (sourceNode.nodeName === 'FX-CONTROL') {
|
|
210
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()} ref="${sourceNode.getAttribute('ref')}">`;
|
|
211
|
-
} else if (sourceNode.nodeName === 'FX-SEND') {
|
|
212
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()} submission="${sourceNode.getAttribute('submission')}">`;
|
|
213
|
-
} else if (sourceNode.nodeName === 'FX-SETVALUE') {
|
|
214
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()} ref="${sourceNode.getAttribute('ref')}">`;
|
|
215
|
-
} else if (sourceNode.nodeName === 'FX-SUBMISSION') {
|
|
216
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()} id="${sourceNode.getAttribute('id')}">`;
|
|
217
|
-
} else {
|
|
218
|
-
*/
|
|
219
|
-
const attrString = Array.from(sourceNode.attributes)
|
|
220
|
-
.filter(attr =>
|
|
221
|
-
this.isInstanceViewer ? true : isAttributeShown(attr.name, sourceNode),
|
|
222
|
-
)
|
|
223
|
-
.map(attr => `${attr.name}="${attr.value}"`)
|
|
224
|
-
.join(' ');
|
|
225
|
-
tagStart.textContent = `<${sourceNode.nodeName.toLowerCase()}${
|
|
226
|
-
attrString ? ` ${attrString}` : ''
|
|
227
|
-
}>`;
|
|
228
|
-
// }
|
|
229
|
-
|
|
230
|
-
if (withChildren) {
|
|
231
|
-
tagEnd = newElement('span');
|
|
232
|
-
addClass(tagEnd, 'adi-end-node');
|
|
233
|
-
tagEnd.textContent = `</${sourceNode.nodeName.toLowerCase()}>`;
|
|
234
|
-
}
|
|
235
|
-
} else {
|
|
236
|
-
tagStart.textContent = sourceNode.nodeName.toLowerCase();
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
elem.appendChild(tagStart);
|
|
241
|
-
/*
|
|
242
|
-
const icon = document.createElement('span');
|
|
243
|
-
icon.textContent = 'x';
|
|
244
|
-
icon.classList.add(('icon'))
|
|
245
|
-
const icon2 = document.createElement('span');
|
|
246
|
-
icon2.textContent = '<-';
|
|
247
|
-
icon2.classList.add(('icon'))
|
|
248
|
-
elem.appendChild(icon);
|
|
249
|
-
elem.appendChild(icon2);
|
|
250
|
-
*/
|
|
251
|
-
if (sourceNode.nodeName.startsWith('FX-')) {
|
|
252
|
-
tagStart.classList.add('fore-node');
|
|
253
|
-
tagStart.classList.add(sourceNode.nodeName.toLowerCase());
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (tagEnd) {
|
|
257
|
-
elem.appendChild(tagEnd);
|
|
258
|
-
|
|
259
|
-
if (sourceNode.nodeName.startsWith('FX-')) {
|
|
260
|
-
tagEnd.classList.add('fore-node');
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return elem;
|
|
265
|
-
}
|
|
266
|
-
return null;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Renders the DOM Tree view
|
|
270
|
-
drawDOM(root, elem, isRoot) {
|
|
271
|
-
if (typeof root !== 'object') {
|
|
272
|
-
throw new Error(`drawDOM: Expected argument root of type object, ${typeof root} given.`);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
let newNode = null;
|
|
276
|
-
let isOpen = true;
|
|
277
|
-
|
|
278
|
-
const adiNode = elem.nodeName.startsWith('FX-')
|
|
279
|
-
? `adi-node ${node.nodeName.toLowerCase()}`
|
|
280
|
-
: '';
|
|
281
|
-
|
|
282
|
-
if (isRoot && this.options.nodeTypes.indexOf(root.nodeType) !== -1) {
|
|
283
|
-
elem.innerHTML = '';
|
|
284
|
-
newNode = this.newTreeNode(root);
|
|
285
|
-
|
|
286
|
-
if (this.hasRequiredNodes(root)) {
|
|
287
|
-
newNode.appendChild(newElement('ul', { 'data-open': true, class: adiNode }));
|
|
288
|
-
|
|
289
|
-
addClass(newNode.querySelector('.adi-trigger'), 'opened');
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
elem.appendChild(newNode);
|
|
293
|
-
elem = elem.querySelector('ul');
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// recursive DOM traversal
|
|
297
|
-
for (let i = 0, len = root.childNodes.length; i < len; i += 1) {
|
|
298
|
-
const node = root.childNodes[i];
|
|
299
|
-
const withChildren = this.hasRequiredNodes(node);
|
|
300
|
-
|
|
301
|
-
if (this.options.nodeTypes.indexOf(node.nodeType) !== -1) {
|
|
302
|
-
newNode = this.newTreeNode(node);
|
|
303
|
-
|
|
304
|
-
if (newNode) {
|
|
305
|
-
if (withChildren) {
|
|
306
|
-
if (this.options.foldText) {
|
|
307
|
-
isOpen = !containsOnlyText(node, true);
|
|
308
|
-
} else {
|
|
309
|
-
isOpen = true;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (node.nodeName === 'HEAD') isOpen = false;
|
|
313
|
-
if (node.nodeName === 'SELECT') isOpen = false;
|
|
314
|
-
if (node.nodeName === 'FX-INSTANCE') isOpen = false;
|
|
315
|
-
/*
|
|
316
|
-
if(this.options.closedElements.includes(node.nodeName.toLowerCase())){
|
|
317
|
-
isOpen = false;
|
|
318
|
-
}
|
|
319
|
-
*/
|
|
320
|
-
|
|
321
|
-
if (node.nodeType === Node.DOCUMENT_NODE) {
|
|
322
|
-
newNode.appendChild(newElement('ul', { 'data-open': isOpen, class: adiNode }));
|
|
323
|
-
} else {
|
|
324
|
-
newNode.insertBefore(
|
|
325
|
-
newElement('ul', { 'data-open': isOpen, class: adiNode }),
|
|
326
|
-
newNode.lastChild,
|
|
327
|
-
);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
addClass(newNode.querySelector('.adi-trigger'), isOpen ? 'opened' : 'closed');
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
elem.appendChild(newNode);
|
|
334
|
-
|
|
335
|
-
if (this.getSelected() === node) {
|
|
336
|
-
const span = newNode.querySelector('span.adi-normal-node');
|
|
337
|
-
span?.classList?.add('adi-active-node');
|
|
338
|
-
this.activeElement = span;
|
|
339
|
-
newNode.scrollIntoView({ block: 'nearest', behavior: 'instant' });
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
if (withChildren) {
|
|
343
|
-
this.drawDOM(node, newNode.querySelector('ul'), false);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// Show/hide the options view
|
|
351
|
-
toggleOptions() {
|
|
352
|
-
if (this.optsView.className.indexOf('adi-hidden') !== -1) {
|
|
353
|
-
removeClass(this.optsView, 'adi-hidden');
|
|
354
|
-
} else {
|
|
355
|
-
addClass(this.optsView, 'adi-hidden');
|
|
356
|
-
this.attrView.querySelector('.adi-content').innerHTML = '';
|
|
357
|
-
this.refreshUI();
|
|
358
|
-
this.drawDOM(document, this.domView.querySelector('.adi-tree-view'), true);
|
|
359
|
-
if (this.options.saving) {
|
|
360
|
-
this.saveOptions();
|
|
361
|
-
} else {
|
|
362
|
-
window.localStorage.removeItem('ADI.options');
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Renders the UI
|
|
368
|
-
drawUI(rootElement) {
|
|
369
|
-
this.uiView = newElement('div', {
|
|
370
|
-
id: 'adi-wrapper',
|
|
371
|
-
class: this.options.transparent ? 'transparent' : '',
|
|
372
|
-
});
|
|
373
|
-
this.domView = newElement('div', { id: 'adi-dom-view' });
|
|
374
|
-
const domViewContent = newElement('div', { class: 'adi-content', id: 'detailsView' });
|
|
375
|
-
// this.attrView.appendChild(newElement('fx-fore', {src: './lab/inspector-view.html'}));
|
|
376
|
-
|
|
377
|
-
// const horizSplit = newElement('div', {id: 'adi-horiz-split'});
|
|
378
|
-
const domTree = newElement('ul', { class: 'adi-tree-view' });
|
|
379
|
-
const domPathWrap = newElement('div', { class: 'adi-path-wrap' });
|
|
380
|
-
const domPathScrollLeft = newElement('span', { class: 'adi-path-left' });
|
|
381
|
-
const domPathScrollRight = newElement('span', { class: 'adi-path-right' });
|
|
382
|
-
this.menuView = newElement('div', { id: 'adi-panel' });
|
|
383
|
-
const naviButtons = newElement('div', { class: 'adi-menu-wrap' });
|
|
384
|
-
const naviConfig = newElement('a', { class: 'adi-menu-config', title: 'Settings' });
|
|
385
|
-
const naviLookup = newElement('a', { class: 'adi-menu-lookup', title: 'Lookup tool' });
|
|
386
|
-
|
|
387
|
-
// this.horizSplit = horizSplit;
|
|
388
|
-
|
|
389
|
-
this.optsView = drawOptions();
|
|
390
|
-
|
|
391
|
-
// put UI together
|
|
392
|
-
domViewContent.appendChild(domTree);
|
|
393
|
-
this.domView.appendChild(this.menuView);
|
|
394
|
-
this.domView.appendChild(domViewContent);
|
|
395
|
-
|
|
396
|
-
domPathWrap.appendChild(domPathScrollLeft);
|
|
397
|
-
domPathWrap.appendChild(domPathScrollRight);
|
|
398
|
-
naviButtons.appendChild(naviLookup);
|
|
399
|
-
naviButtons.appendChild(naviConfig);
|
|
400
|
-
this.menuView.appendChild(domPathWrap);
|
|
401
|
-
this.menuView.appendChild(naviButtons);
|
|
402
|
-
// this.uiView.appendChild(this.menuView);
|
|
403
|
-
this.uiView.appendChild(this.optsView);
|
|
404
|
-
this.uiView.appendChild(this.domView);
|
|
405
|
-
if (!this.isInstanceViewer) {
|
|
406
|
-
this.attrView = newElement('div', { id: 'adi-attr-view' });
|
|
407
|
-
const attrViewContent = newElement('div', { class: 'adi-content' });
|
|
408
|
-
this.attrView.appendChild(attrViewContent);
|
|
409
|
-
this.uiView.appendChild(this.attrView);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// this.uiView.appendChild(horizSplit);
|
|
413
|
-
// wrapper.appendChild(naviWrap);
|
|
414
|
-
|
|
415
|
-
// cache UI object and append to the DOM
|
|
416
|
-
|
|
417
|
-
rootElement.appendChild(this.uiView);
|
|
418
|
-
// document.querySelector('#inspector').appendChild(wrapper);
|
|
419
|
-
|
|
420
|
-
this.refreshUI(true);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// Refreshes the global UI
|
|
424
|
-
refreshUI(refreshOpts) {
|
|
425
|
-
if (this.uiView === null) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// load options if requested (e.g. before the first UI refresh)
|
|
430
|
-
if (refreshOpts) {
|
|
431
|
-
this.loadOptions();
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Options view refresh
|
|
435
|
-
if (refreshOpts) {
|
|
436
|
-
this.optsView.querySelector('[data-opt="transparent"]').checked = this.options.transparent;
|
|
437
|
-
this.optsView.querySelector('[data-opt="saving"]').checked = this.options.saving;
|
|
438
|
-
this.optsView.querySelector('[data-opt="omitEmptyText"]').checked =
|
|
439
|
-
this.options.omitEmptyText;
|
|
440
|
-
this.optsView.querySelector('[data-opt="makeVisible"]').checked = this.options.makeVisible;
|
|
441
|
-
this.optsView.querySelector('[data-opt="foldText"]').checked = this.options.foldText;
|
|
442
|
-
this.optsView.querySelector('[data-opt="nodeTypes-3"]').checked =
|
|
443
|
-
this.options.nodeTypes.indexOf(3) !== -1;
|
|
444
|
-
this.optsView.querySelector('[data-opt="nodeTypes-8"]').checked =
|
|
445
|
-
this.options.nodeTypes.indexOf(8) !== -1;
|
|
446
|
-
// this.optsView.querySelector('[data-opt="nodeTypes-1"]').checked = this.options.nodeTypes.indexOf(1) !== -1;
|
|
447
|
-
// this.optsView.querySelector('[data-opt="nodeTypes-9"]').checked = this.options.nodeTypes.indexOf(9) !== -1;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// UI appearance refresh
|
|
451
|
-
this.uiView.className = this.options.transparent ? 'transparent' : '';
|
|
452
|
-
// this.uiView.style.display = this.options.visible ? 'grid' : 'none';
|
|
453
|
-
// this.domView.style.height = `${this.options.split}%`;
|
|
454
|
-
// this.attrView.style.height = `${100 - this.options.split}%`;
|
|
455
|
-
this.domView.querySelector('.adi-content').style.height = `${this.domView.clientHeight}px`;
|
|
456
|
-
if (!this.isInstanceViewer) {
|
|
457
|
-
this.attrView.querySelector('.adi-content').style.height = `${
|
|
458
|
-
this.attrView.clientHeight - this.menuView.clientHeight
|
|
459
|
-
}px`;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
addClass(this.uiView, this.options.align);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// UI visibility toggle handler
|
|
466
|
-
toggleVisibilityUI() {
|
|
467
|
-
if (this.uiView === null) {
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
this.uiView.style.display = this.options.visible ? 'none' : 'block';
|
|
472
|
-
this.options.visible = !this.options.visible;
|
|
473
|
-
this.saveOptions();
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// Renders the attribute view
|
|
477
|
-
drawAttrs(elem) {
|
|
478
|
-
if (this.isInstanceViewer) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
const content = this.attrView.querySelector('.adi-content');
|
|
482
|
-
// prepare attributes
|
|
483
|
-
content.innerHTML = '';
|
|
484
|
-
|
|
485
|
-
const header = document.createElement('header');
|
|
486
|
-
header.innerText = 'Attributes';
|
|
487
|
-
content.appendChild(header);
|
|
488
|
-
|
|
489
|
-
// todo: hook element-def.json in here
|
|
490
|
-
/*
|
|
491
|
-
if (elem.nodeName.startsWith('FX-')) {
|
|
492
|
-
console.log('got a fore element');
|
|
493
|
-
const {properties} = elem.constructor;
|
|
494
|
-
Object.keys(properties).forEach(propertyName => {
|
|
495
|
-
|
|
496
|
-
const property = properties[propertyName];
|
|
497
|
-
if (!property || property.hidden) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
const row = content.appendChild(newElement('span', {class: 'adi-attr'}));
|
|
501
|
-
|
|
502
|
-
switch (property.type) {
|
|
503
|
-
case 'referencedNode': {
|
|
504
|
-
row.innerHTML = `<label>${propertyName}: <button>${elem[propertyName]?.nodeName}</button></label>`;
|
|
505
|
-
const button = row.querySelector('button');
|
|
506
|
-
button.addEventListener(
|
|
507
|
-
'click', () => this.handleLookup({detail: {target: elem[propertyName]}})
|
|
508
|
-
);
|
|
509
|
-
break;
|
|
510
|
-
}
|
|
511
|
-
case Number: {
|
|
512
|
-
row.innerHTML = `<label>${propertyName}: <input type="number" data-attr="${propertyName}" value="${elem[propertyName]}"></label>`;
|
|
513
|
-
break;
|
|
514
|
-
}
|
|
515
|
-
case String: {
|
|
516
|
-
if (property.valueSpace) {
|
|
517
|
-
row.innerHTML = `<label>${propertyName}: <select data-attr="${propertyName}" value="${elem[propertyName]}">${property.valueSpace.map(value => `<option>${value}</option>`)}</label>`;
|
|
518
|
-
break;
|
|
519
|
-
|
|
520
|
-
}
|
|
521
|
-
row.innerHTML = `<label>${propertyName}: <input type="text" data-attr="${propertyName}" value="${elem[propertyName]}"></label>`;
|
|
522
|
-
break;
|
|
523
|
-
}
|
|
524
|
-
case Boolean: {
|
|
525
|
-
if (property.valueSpace) {
|
|
526
|
-
row.innerHTML = `<label>${propertyName}: <input type="checkbox" data-attr="${propertyName}" value="${elem[propertyName]}"></input></label>`;
|
|
527
|
-
|
|
528
|
-
}
|
|
529
|
-
break;
|
|
530
|
-
}
|
|
531
|
-
case Object: {
|
|
532
|
-
try {
|
|
533
|
-
row.innerHTML = `<label>${propertyName}: <code>${JSON.stringify(elem[propertyName])}</code></label>`;
|
|
534
|
-
} catch (err) {
|
|
535
|
-
row.innerHTML = `<label>${propertyName}: <code>Unserializable</code></label>`;
|
|
536
|
-
}
|
|
537
|
-
break;
|
|
538
|
-
}
|
|
539
|
-
case Map: {
|
|
540
|
-
try {
|
|
541
|
-
row.innerHTML = `<label>${propertyName}: <code>${JSON.stringify(elem[propertyName])}</code></label>`;
|
|
542
|
-
} catch (err) {
|
|
543
|
-
row.innerHTML = `<label>${propertyName}: <code>Unserializable</code></label>`;
|
|
544
|
-
}
|
|
545
|
-
break;
|
|
546
|
-
}
|
|
547
|
-
default: {
|
|
548
|
-
row.innerHTML = `<label>${propertyName}: Unknown type ${property.type}</label>`;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
} else {
|
|
553
|
-
*/
|
|
554
|
-
[...elem.attributes].forEach(attr => {
|
|
555
|
-
if (attr.name !== 'style') {
|
|
556
|
-
content.appendChild(drawAttrRow(attr.name, attr.value));
|
|
557
|
-
}
|
|
558
|
-
});
|
|
559
|
-
// }
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Handles attribute changes
|
|
563
|
-
changeAttribute(e) {
|
|
564
|
-
const target = e ? e.target : window.event.srcElement;
|
|
565
|
-
const attr = target.getAttribute('data-attr');
|
|
566
|
-
const val = target.value;
|
|
567
|
-
const elem = this.getSelected();
|
|
568
|
-
|
|
569
|
-
// remove attribute if the new value is empty
|
|
570
|
-
if (val === '') {
|
|
571
|
-
elem.removeAttribute(attr);
|
|
572
|
-
} else {
|
|
573
|
-
elem.setAttribute(attr, val);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// Handles option changes
|
|
578
|
-
changeOption(e) {
|
|
579
|
-
const target = e ? e.target : window.event.srcElement;
|
|
580
|
-
const data = target.getAttribute('data-opt');
|
|
581
|
-
const val = target.checked;
|
|
582
|
-
|
|
583
|
-
if (data.indexOf('nodeTypes') !== -1) {
|
|
584
|
-
const type = parseInt(data.match(/\d+/)[0], 10);
|
|
585
|
-
|
|
586
|
-
if (val) {
|
|
587
|
-
this.options.nodeTypes.push(type);
|
|
588
|
-
} else {
|
|
589
|
-
this.options.nodeTypes.splice(this.options.nodeTypes.indexOf(type), 1);
|
|
590
|
-
}
|
|
591
|
-
} else {
|
|
592
|
-
this.options[data] = val;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// Key events processing
|
|
597
|
-
processKey(e) {
|
|
598
|
-
e = e || window.event;
|
|
599
|
-
const code = e.keyCode || e.which;
|
|
600
|
-
|
|
601
|
-
switch (code) {
|
|
602
|
-
case 272: // ctrl + alt + d
|
|
603
|
-
this.toggleVisibilityUI();
|
|
604
|
-
break;
|
|
605
|
-
default:
|
|
606
|
-
break;
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// Vertical splitter resize handler
|
|
611
|
-
verticalResize(e) {
|
|
612
|
-
if (!this.vertResizing) {
|
|
613
|
-
return;
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
e = e || window.event;
|
|
617
|
-
document.documentElement.style.cursor = 'e-resize';
|
|
618
|
-
const nWidth = this.options.width + this.xPos - e.clientX;
|
|
619
|
-
|
|
620
|
-
if (nWidth >= this.options.minWidth) {
|
|
621
|
-
this.options.width = nWidth;
|
|
622
|
-
this.xPos = e.clientX;
|
|
623
|
-
this.refreshUI();
|
|
624
|
-
this.saveOptions();
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
// Horizontal splitter resize handler
|
|
629
|
-
horizontalResize(e) {
|
|
630
|
-
if (!this.horizResizing) {
|
|
631
|
-
return;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
e = e || window.event;
|
|
635
|
-
document.documentElement.style.cursor = 'n-resize';
|
|
636
|
-
const nSplit = Math.floor((e.clientY / this.uiView.clientHeight) * 100);
|
|
637
|
-
|
|
638
|
-
if (nSplit >= this.options.minSplit && nSplit <= 100 - this.options.minSplit) {
|
|
639
|
-
this.options.split = nSplit;
|
|
640
|
-
this.refreshUI();
|
|
641
|
-
this.saveOptions();
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
processExecuteAction(e) {
|
|
646
|
-
this.refreshUI();
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
// Handles active element selection
|
|
650
|
-
handleActive(e) {
|
|
651
|
-
let target = e ? e.detail?.target || e.target : window.event.srcElement;
|
|
652
|
-
const active = this.domView.querySelector('.adi-active-node');
|
|
653
|
-
|
|
654
|
-
if (active) {
|
|
655
|
-
removeClass(active, 'adi-active-node');
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
// clicked on normal-node or end-node?
|
|
659
|
-
if (!target || target.nodeType === Node.DOCUMENT_NODE) return;
|
|
660
|
-
if (target && target.classList && target.classList.contains('adi-end-node')) {
|
|
661
|
-
target = target.parentNode.querySelector('.adi-normal-node');
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
this.activeElement = target;
|
|
665
|
-
addClass(target, 'adi-active-node');
|
|
666
|
-
|
|
667
|
-
/*
|
|
668
|
-
e.target.dispatchEvent(
|
|
669
|
-
new CustomEvent('handle-active', {
|
|
670
|
-
composed: true,
|
|
671
|
-
bubbles: true,
|
|
672
|
-
detail: {active: this.activeElement, selected: this.getSelected()},
|
|
673
|
-
}),
|
|
674
|
-
);
|
|
675
|
-
*/
|
|
676
|
-
|
|
677
|
-
// make it visible (scroll)
|
|
678
|
-
if (this.options.makeVisible) {
|
|
679
|
-
const wrap = this.domView.querySelector('.adi-content');
|
|
680
|
-
wrap.scrollIntoView({ block: 'center', behavior: 'instant' });
|
|
681
|
-
}
|
|
682
|
-
const selected = this.getSelected();
|
|
683
|
-
this.drawAttrs(selected);
|
|
684
|
-
|
|
685
|
-
if (selected && typeof selected.getModelItem === 'function' && selected.getModelItem()?.node) {
|
|
686
|
-
let selectedElement = selected.modelItem.node;
|
|
687
|
-
if (selectedElement?.nodeType === Node.ATTRIBUTE_NODE) {
|
|
688
|
-
selectedElement = selectedElement.ownerElement;
|
|
689
|
-
}
|
|
690
|
-
window.document.dispatchEvent(
|
|
691
|
-
new CustomEvent('log-active-element', { detail: { target: selectedElement } }),
|
|
692
|
-
);
|
|
693
|
-
}
|
|
694
|
-
// window.document.dispatchEvent(new CustomEvent('log-active-element', {detail: {target: selected}}));
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
// Highlights an element on page
|
|
698
|
-
highlightElement(event) {
|
|
699
|
-
// console.log('highlight',e);
|
|
700
|
-
let sourceNode = event ? event.target : window.event.srcElement;
|
|
701
|
-
|
|
702
|
-
if (sourceNode.classList.contains('adi-end-node')) {
|
|
703
|
-
sourceNode = sourceNode.parentNode.querySelector('.adi-normal-node');
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
const inspectorNode = this.sourceNodeByInspectorNodeLookup.get(sourceNode);
|
|
707
|
-
|
|
708
|
-
if (!inspectorNode || inspectorNode.ownerDocument !== window.document) {
|
|
709
|
-
// Not in HTML: ignore
|
|
710
|
-
return;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
if (inspectorNode) {
|
|
714
|
-
if (event.type === 'mouseover') {
|
|
715
|
-
this.styleBackup = inspectorNode.getAttribute('style') || '';
|
|
716
|
-
inspectorNode.setAttribute('style', `outline: 2px solid blue; ${this.styleBackup}`);
|
|
717
|
-
} else if (this.styleBackup === '') {
|
|
718
|
-
inspectorNode.removeAttribute('style');
|
|
719
|
-
} else {
|
|
720
|
-
inspectorNode.setAttribute('style', this.styleBackup);
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
// Handles element lookup on page
|
|
726
|
-
handleLookup(e) {
|
|
727
|
-
const target = e ? e.detail?.target || e.target : window.event.srcElement;
|
|
728
|
-
|
|
729
|
-
if (!this.document.contains(target)) {
|
|
730
|
-
// Targetted at somewhere else!!!
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
if (target.nodeType === Node.DOCUMENT_NODE) {
|
|
734
|
-
// Targetted at the document node. Nothing to highlight
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
if (target.className.indexOf('adi-menu-lookup') !== -1) {
|
|
739
|
-
// enable/disable interactive lookup
|
|
740
|
-
if (this.elemLookup) {
|
|
741
|
-
removeClass(target, 'adi-active');
|
|
742
|
-
this.elemLookup = false;
|
|
743
|
-
this.removeEvent(document.body, 'mouseover', this.handleLookup, true);
|
|
744
|
-
this.removeEvent(document.body, 'mouseout', this.handleLookup, true);
|
|
745
|
-
this.removeEvent(document.body, 'click', this.handleLookup, true);
|
|
746
|
-
return;
|
|
747
|
-
}
|
|
748
|
-
addClass(target, 'adi-active');
|
|
749
|
-
this.elemLookup = true;
|
|
750
|
-
this.addEventDelegate(
|
|
751
|
-
document.body,
|
|
752
|
-
'mouseover',
|
|
753
|
-
this.handleLookup,
|
|
754
|
-
false,
|
|
755
|
-
'*',
|
|
756
|
-
true,
|
|
757
|
-
'adi-wrapper',
|
|
758
|
-
);
|
|
759
|
-
this.addEventDelegate(
|
|
760
|
-
document.body,
|
|
761
|
-
'mouseout',
|
|
762
|
-
this.handleLookup,
|
|
763
|
-
false,
|
|
764
|
-
'*',
|
|
765
|
-
true,
|
|
766
|
-
'adi-wrapper',
|
|
767
|
-
);
|
|
768
|
-
this.addEventDelegate(
|
|
769
|
-
document.body,
|
|
770
|
-
'click',
|
|
771
|
-
this.handleLookup,
|
|
772
|
-
false,
|
|
773
|
-
'*',
|
|
774
|
-
true,
|
|
775
|
-
'adi-wrapper',
|
|
776
|
-
);
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
// handle lookup events
|
|
780
|
-
if (e.type === 'mouseover') {
|
|
781
|
-
this.styleBackup = target.getAttribute('style') || '';
|
|
782
|
-
target.setAttribute('style', `outline: 1px dashed red; ${this.styleBackup}`);
|
|
783
|
-
return;
|
|
784
|
-
}
|
|
785
|
-
if (e.type === 'mouseout') {
|
|
786
|
-
target.setAttribute('style', this.styleBackup);
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
this.elemLookup = false;
|
|
790
|
-
removeClass(this.menuView.querySelector('.adi-menu-lookup'), 'adi-active');
|
|
791
|
-
target.setAttribute('style', this.styleBackup);
|
|
792
|
-
this.removeEvent(document.body, 'mouseover', this.handleLookup, true);
|
|
793
|
-
this.removeEvent(document.body, 'mouseout', this.handleLookup, true);
|
|
794
|
-
this.removeEvent(document.body, 'click', this.handleLookup, true);
|
|
795
|
-
pauseEvent(e);
|
|
796
|
-
|
|
797
|
-
// find corresponding node in the DOM view
|
|
798
|
-
const active = this.sourceNodeByInspectorNodeLookup.get(target);
|
|
799
|
-
|
|
800
|
-
// activate it
|
|
801
|
-
if (!active) return;
|
|
802
|
-
if (active) {
|
|
803
|
-
active.click();
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
// open the whole path in DOM view
|
|
807
|
-
if (!active.parentNode) return;
|
|
808
|
-
let node = active.parentNode;
|
|
809
|
-
let tmp;
|
|
810
|
-
|
|
811
|
-
if (node.querySelector('ul')) {
|
|
812
|
-
node.querySelector('ul').setAttribute('data-open', 'true');
|
|
813
|
-
}
|
|
814
|
-
while (node !== this.domView.querySelector('.adi-content')) {
|
|
815
|
-
if (node.className.indexOf('adi-node') !== -1) {
|
|
816
|
-
tmp = node.querySelector('.adi-trigger');
|
|
817
|
-
if (tmp) {
|
|
818
|
-
removeClass(tmp, 'closed');
|
|
819
|
-
addClass(tmp, 'opened');
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
node = node.parentNode; // ul node
|
|
823
|
-
node.setAttribute('data-open', 'true');
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
node = node.parentNode;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
// make it visible (scroll)
|
|
830
|
-
if (this.options.makeVisible) {
|
|
831
|
-
active.scrollIntoView({ behavior: 'instant', block: 'nearest', inline: 'nearest' });
|
|
832
|
-
}
|
|
833
|
-
target.scrollIntoView({ behavior: 'instant', block: 'nearest', inline: 'nearest' });
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
// Simple cross-browser event handler that enables simple event delegation.
|
|
837
|
-
// Note that the selector must be a string and no nesting is supported.
|
|
838
|
-
// Selector is expected to be in one of formats listed below and works for all children
|
|
839
|
-
// in the particular element.
|
|
840
|
-
// Store parameter enables storing the reference to custom event handler.
|
|
841
|
-
// Exclude parameter will exclude the particular element and all of its children, this works
|
|
842
|
-
// only for id selectors.
|
|
843
|
-
// Selector formats: tag name ("div"), class name (".my-class"), id ("#my-id") and any ("*").
|
|
844
|
-
|
|
845
|
-
addEventDelegate(elem, evt, fn, capture, selector, store, exclude) {
|
|
846
|
-
// custom event handler is registered
|
|
847
|
-
const handler = e => {
|
|
848
|
-
// check if target corresponds to the selector
|
|
849
|
-
const target = e ? e.target : window.event.srcElement;
|
|
850
|
-
const sel = selector.substr(1);
|
|
851
|
-
let delegate = false;
|
|
852
|
-
|
|
853
|
-
if (exclude) {
|
|
854
|
-
let node = target;
|
|
855
|
-
|
|
856
|
-
while (node !== document) {
|
|
857
|
-
if (node.id === exclude) {
|
|
858
|
-
return;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
node = node.parentNode;
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// should the event be delegated?
|
|
866
|
-
if (selector.indexOf('#') === 0) {
|
|
867
|
-
// ID
|
|
868
|
-
delegate = target.id === sel;
|
|
869
|
-
} else if (selector.indexOf('.') === 0) {
|
|
870
|
-
// class
|
|
871
|
-
delegate = target.className.indexOf(sel) !== -1;
|
|
872
|
-
} else if (selector === '*') {
|
|
873
|
-
// any
|
|
874
|
-
delegate = true;
|
|
875
|
-
} else {
|
|
876
|
-
// tag name
|
|
877
|
-
delegate = target.nodeName.toLowerCase() === selector;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
// delegate the event handling
|
|
881
|
-
if (delegate) {
|
|
882
|
-
fn(e);
|
|
883
|
-
}
|
|
884
|
-
};
|
|
885
|
-
// save the reference
|
|
886
|
-
if (store) {
|
|
887
|
-
this.delegatedEvents.push({
|
|
888
|
-
handle: handler,
|
|
889
|
-
elem,
|
|
890
|
-
fn,
|
|
891
|
-
evt,
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
elem.addEventListener(evt, handler, capture);
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
// Simple cross-browser event removing
|
|
899
|
-
removeEvent(elem, evt, fn, wasDelegated) {
|
|
900
|
-
if (typeof elem !== 'object') {
|
|
901
|
-
throw new Error(`addEvent: Expected argument elem of type object, ${typeof elem} given.`);
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
// try to find stored delegated event
|
|
905
|
-
let stored = null;
|
|
906
|
-
if (wasDelegated) {
|
|
907
|
-
for (let i = 0, len = this.delegatedEvents.length; i < len; i += 1) {
|
|
908
|
-
stored = this.delegatedEvents[i];
|
|
909
|
-
if (stored.elem === elem && stored.evt === evt && stored.fn === fn) {
|
|
910
|
-
fn = stored.handle;
|
|
911
|
-
this.delegatedEvents.splice(i, 1);
|
|
912
|
-
break;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
// elem.detachEvent(`on${evt}`, fn);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
// Event registration
|
|
921
|
-
registerEvents() {
|
|
922
|
-
// events for splitters
|
|
923
|
-
/*
|
|
924
|
-
this.horizSplit.addEventListener(
|
|
925
|
-
'mousedown',
|
|
926
|
-
e => {
|
|
927
|
-
e = e || window.event;
|
|
928
|
-
pauseEvent(e);
|
|
929
|
-
this.horizResizing = true;
|
|
930
|
-
},
|
|
931
|
-
false,
|
|
932
|
-
);
|
|
933
|
-
*/
|
|
934
|
-
|
|
935
|
-
const redrawUi = () => {
|
|
936
|
-
if (this.instanceId !== '#document') {
|
|
937
|
-
const instance = window.document.querySelector(`#${this.instanceId}`);
|
|
938
|
-
this.document = instance.getInstanceData();
|
|
939
|
-
}
|
|
940
|
-
this.drawDOM(this.document, this.domView.querySelector('.adi-tree-view'), true);
|
|
941
|
-
};
|
|
942
|
-
|
|
943
|
-
// Update UI when something with instances changed
|
|
944
|
-
document.addEventListener('instance-loaded', redrawUi);
|
|
945
|
-
// Update UI when some value changes
|
|
946
|
-
document.addEventListener('value-changed', redrawUi);
|
|
947
|
-
// Update UI when we're done loading and all repeats are done
|
|
948
|
-
document.addEventListener('ready', redrawUi);
|
|
949
|
-
|
|
950
|
-
document.addEventListener(
|
|
951
|
-
'mouseup',
|
|
952
|
-
() => {
|
|
953
|
-
document.documentElement.style.cursor = 'default';
|
|
954
|
-
this.vertResizing = false;
|
|
955
|
-
this.horizResizing = false;
|
|
956
|
-
},
|
|
957
|
-
false,
|
|
958
|
-
);
|
|
959
|
-
|
|
960
|
-
document.addEventListener('mousemove', event => this.verticalResize(event), false);
|
|
961
|
-
document.addEventListener('mousemove', event => this.horizontalResize(event), false);
|
|
962
|
-
// window resize
|
|
963
|
-
window.addEventListener('resize', event => this.refreshUI(event), false);
|
|
964
|
-
|
|
965
|
-
// keypress events
|
|
966
|
-
document.addEventListener('keypress', event => this.processKey(event), false);
|
|
967
|
-
|
|
968
|
-
// fore action events
|
|
969
|
-
document.addEventListener('log-active-element', event => this.handleLookup(event), false);
|
|
970
|
-
|
|
971
|
-
// Dom view folding handler
|
|
972
|
-
const handleFolding = e => {
|
|
973
|
-
const target = e ? e.target : window.event.srcElement;
|
|
974
|
-
const ul = target.parentNode.querySelector('ul');
|
|
975
|
-
|
|
976
|
-
if (ul.getAttribute('data-open') === 'true') {
|
|
977
|
-
removeClass(target, 'opened');
|
|
978
|
-
addClass(target, 'closed');
|
|
979
|
-
ul.setAttribute('data-open', 'false');
|
|
980
|
-
} else {
|
|
981
|
-
removeClass(target, 'closed');
|
|
982
|
-
addClass(target, 'opened');
|
|
983
|
-
ul.setAttribute('data-open', 'true');
|
|
984
|
-
}
|
|
985
|
-
};
|
|
986
|
-
|
|
987
|
-
// dom tree view folding
|
|
988
|
-
this.addEventDelegate(this.domView, 'click', handleFolding, false, '.adi-trigger');
|
|
989
|
-
|
|
990
|
-
// active element
|
|
991
|
-
this.addEventDelegate(
|
|
992
|
-
this.domView,
|
|
993
|
-
'click',
|
|
994
|
-
event => this.handleActive(event),
|
|
995
|
-
false,
|
|
996
|
-
'.adi-normal-node',
|
|
997
|
-
);
|
|
998
|
-
this.addEventDelegate(
|
|
999
|
-
this.domView,
|
|
1000
|
-
'click',
|
|
1001
|
-
event => this.handleActive(event),
|
|
1002
|
-
false,
|
|
1003
|
-
'.adi-end-node',
|
|
1004
|
-
);
|
|
1005
|
-
|
|
1006
|
-
// matching tag highlighting
|
|
1007
|
-
this.addEventDelegate(
|
|
1008
|
-
this.domView,
|
|
1009
|
-
'mouseover',
|
|
1010
|
-
e => {
|
|
1011
|
-
const target = e ? e.target : window.event.srcElement;
|
|
1012
|
-
addClass(target.parentNode.querySelector('.adi-normal-node'), 'hover');
|
|
1013
|
-
},
|
|
1014
|
-
false,
|
|
1015
|
-
'.adi-end-node',
|
|
1016
|
-
);
|
|
1017
|
-
this.addEventDelegate(
|
|
1018
|
-
this.domView,
|
|
1019
|
-
'mouseout',
|
|
1020
|
-
e => {
|
|
1021
|
-
const target = e ? e.target : window.event.srcElement;
|
|
1022
|
-
removeClass(target.parentNode.querySelector('.adi-normal-node'), 'hover');
|
|
1023
|
-
},
|
|
1024
|
-
false,
|
|
1025
|
-
'.adi-end-node',
|
|
1026
|
-
);
|
|
1027
|
-
|
|
1028
|
-
// page element highlighting
|
|
1029
|
-
this.addEventDelegate(
|
|
1030
|
-
this.domView,
|
|
1031
|
-
'mouseover',
|
|
1032
|
-
event => this.highlightElement(event),
|
|
1033
|
-
false,
|
|
1034
|
-
'.adi-end-node',
|
|
1035
|
-
);
|
|
1036
|
-
this.addEventDelegate(
|
|
1037
|
-
this.domView,
|
|
1038
|
-
'mouseover',
|
|
1039
|
-
event => this.highlightElement(event),
|
|
1040
|
-
false,
|
|
1041
|
-
'.adi-normal-node',
|
|
1042
|
-
);
|
|
1043
|
-
this.addEventDelegate(
|
|
1044
|
-
this.domView,
|
|
1045
|
-
'mouseout',
|
|
1046
|
-
event => this.highlightElement(event),
|
|
1047
|
-
false,
|
|
1048
|
-
'.adi-end-node',
|
|
1049
|
-
);
|
|
1050
|
-
this.addEventDelegate(
|
|
1051
|
-
this.domView,
|
|
1052
|
-
'mouseout',
|
|
1053
|
-
event => this.highlightElement(event),
|
|
1054
|
-
false,
|
|
1055
|
-
'.adi-normal-node',
|
|
1056
|
-
);
|
|
1057
|
-
|
|
1058
|
-
// element lookup
|
|
1059
|
-
this.menuView
|
|
1060
|
-
.querySelector('.adi-menu-lookup')
|
|
1061
|
-
.addEventListener('click', event => this.handleLookup(event), false);
|
|
1062
|
-
|
|
1063
|
-
document.addEventListener('handle-active', e => {
|
|
1064
|
-
if (e.detail.selected === this.getSelected()) {
|
|
1065
|
-
// We caused this. ignore
|
|
1066
|
-
return;
|
|
1067
|
-
}
|
|
1068
|
-
const { selected } = e.detail;
|
|
1069
|
-
const target = this.sourceNodeByInspectorNodeLookup.get(selected);
|
|
1070
|
-
// make it visible (scroll)
|
|
1071
|
-
if (this.options.makeVisible) {
|
|
1072
|
-
const wrap = this.domView.querySelector('.adi-content');
|
|
1073
|
-
if (target.offsetTop >= wrap.clientHeight || target.offsetTop <= wrap.scrollTop) {
|
|
1074
|
-
wrap.scrollTop = target.offsetTop - Math.floor(wrap.clientHeight / 2);
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
this.drawAttrs(this.getSelected());
|
|
1079
|
-
});
|
|
1080
|
-
|
|
1081
|
-
document.addEventListener('execute-action', e => this.processExecuteAction(event), {
|
|
1082
|
-
capture: true,
|
|
1083
|
-
});
|
|
1084
|
-
|
|
1085
|
-
// options events
|
|
1086
|
-
this.addEventDelegate(
|
|
1087
|
-
this.optsView,
|
|
1088
|
-
'change',
|
|
1089
|
-
event => this.changeOption(event),
|
|
1090
|
-
false,
|
|
1091
|
-
'input',
|
|
1092
|
-
);
|
|
1093
|
-
this.addEventDelegate(
|
|
1094
|
-
this.optsView,
|
|
1095
|
-
'click',
|
|
1096
|
-
event => this.toggleOptions(event),
|
|
1097
|
-
false,
|
|
1098
|
-
'.adi-opt-close',
|
|
1099
|
-
);
|
|
1100
|
-
this.menuView
|
|
1101
|
-
.querySelector('.adi-menu-config')
|
|
1102
|
-
.addEventListener('click', event => this.toggleOptions(event), false);
|
|
1103
|
-
|
|
1104
|
-
// attributes events
|
|
1105
|
-
if (!this.isInstanceViewer) {
|
|
1106
|
-
this.addEventDelegate(this.attrView, 'change', this.changeAttribute, false, 'input');
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
export default ADI;
|