datafolder 1.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 +169 -0
- package/index.js +3 -0
- package/package.json +27 -0
- package/sample.js +37 -0
- package/scripts/airbnb.js +73 -0
- package/scripts/airbnb2.js +74 -0
- package/scripts/airbnb2_queries.js +231 -0
- package/scripts/airbnb_queries.js +264 -0
- package/scripts/downloadFile.js +42 -0
- package/scripts/express.js +46 -0
- package/scripts/fastify.js +79 -0
- package/scripts/flights.js +75 -0
- package/scripts/flights2.js +81 -0
- package/scripts/flights2_queries.js +453 -0
- package/scripts/flights_queries.js +403 -0
- package/src/QyAcl.js +252 -0
- package/src/QyAclSaver.js +14 -0
- package/src/QyAclSaver_Worker.js +29 -0
- package/src/QyAclWriter.js +19 -0
- package/src/QyBatch.js +501 -0
- package/src/QyBinWriter.js +140 -0
- package/src/QyCD.js +61 -0
- package/src/QyCache.js +212 -0
- package/src/QyCompressor.js +60 -0
- package/src/QyCompressor_Worker.js +13 -0
- package/src/QyDB.js +122 -0
- package/src/QyDefaultOptions.js +59 -0
- package/src/QyDir.js +192 -0
- package/src/QyFetch.js +38 -0
- package/src/QyFile.js +124 -0
- package/src/QyFileContentUtils.js +175 -0
- package/src/QyFileLogger.js +58 -0
- package/src/QyIndex.js +237 -0
- package/src/QyIndexPropTree.js +92 -0
- package/src/QyIntersectNode.js +48 -0
- package/src/QyItem.js +105 -0
- package/src/QyJsonSaver.js +20 -0
- package/src/QyKVData.js +289 -0
- package/src/QyKVDataCleaner.js +17 -0
- package/src/QyKVDataCleaner_Worker.js +94 -0
- package/src/QyKVDataLoader.js +65 -0
- package/src/QyKVDataSaver.js +17 -0
- package/src/QyKVDataSaver_Worker.js +81 -0
- package/src/QyLogFileSaver.js +14 -0
- package/src/QyLogFileSaver_Worker.js +26 -0
- package/src/QyLogger.js +76 -0
- package/src/QyMessageWorker.js +41 -0
- package/src/QyMessager.js +84 -0
- package/src/QyMessager_Run.js +13 -0
- package/src/QyMod.js +15 -0
- package/src/QyOpRunner.js +73 -0
- package/src/QyQueue.js +60 -0
- package/src/QySaver.js +83 -0
- package/src/QySnapshotCompactor.js +17 -0
- package/src/QySnapshotCompactor_Worker.js +151 -0
- package/src/QySnapshotSaver.js +17 -0
- package/src/QySnapshotSaver_Worker.js +164 -0
- package/src/QySnapshots.js +354 -0
- package/src/QyStructure.js +50 -0
- package/src/QyTrigger.js +133 -0
- package/src/QyUnionNode.js +105 -0
- package/src/QyUtils.js +250 -0
- package/src/QyWorker.js +33 -0
- package/src/hackernews.js +93 -0
- package/src/rpc/evalCode.js +9 -0
- package/src/rpc/getFileContent.js +16 -0
- package/src/rpc/getSubItems.js +32 -0
- package/src/rpc/queryFiles.js +33 -0
- package/src/rpc/reloadRpc.js +1 -0
- package/src/simulate.js +114 -0
- package/src/simulate2.js +110 -0
- package/src/soc_pokec.js +43 -0
- package/static/bootstrap-5.3.8-dist/css/bootstrap.min.css +6 -0
- package/static/bootstrap-5.3.8-dist/js/bootstrap.bundle.js +6312 -0
- package/static/datafolderui/QyStyledElement.js +30 -0
- package/static/datafolderui/QyUIFolderTree.js +203 -0
- package/static/datafolderui/QyUIUtils.js +42 -0
- package/static/datafolderui/display-tree.js +108 -0
- package/static/datafolderui/explore-tree.js +122 -0
- package/static/datafolderui/folder-tree.js +5 -0
- package/static/datafolderui/hscrpt.js +25 -0
- package/static/datafolderui/index.css +6 -0
- package/static/datafolderui/index.html +20 -0
- package/static/datafolderui/json-view.js +74 -0
- package/static/datafolderui/kv-input.js +66 -0
- package/static/datafolderui/list-input.js +52 -0
- package/static/datafolderui/main-page.js +98 -0
- package/static/datafolderui/num-input.js +27 -0
- package/static/datafolderui/query-editor.js +229 -0
- package/static/datafolderui/querySelectorShadowRoot.js +24 -0
- package/static/datafolderui/resizable-input.js +67 -0
- package/static/favicon.ico +0 -0
- package/static/icons-1.13.1/font/bootstrap-icons.min.css +5 -0
- package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff +0 -0
- package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff2 +0 -0
- package/static/json-view/dist/jsonview.js +433 -0
- package/static/tree.js/tree.css +106 -0
- package/static/tree.js/tree.js +374 -0
- package/static/w2ui/dist/w2ui.min.css +2 -0
- package/static/w2ui/src/less/icons/icons.json +1 -0
- package/static/w2ui/src/less/icons/preview.html +33 -0
- package/static/w2ui/src/less/icons/readme.md +15 -0
- package/static/w2ui/src/less/icons/svg/box.svg +3 -0
- package/static/w2ui/src/less/icons/svg/check.svg +3 -0
- package/static/w2ui/src/less/icons/svg/colors.svg +3 -0
- package/static/w2ui/src/less/icons/svg/columns.svg +5 -0
- package/static/w2ui/src/less/icons/svg/cross.svg +4 -0
- package/static/w2ui/src/less/icons/svg/drop.svg +6 -0
- package/static/w2ui/src/less/icons/svg/empty.svg +3 -0
- package/static/w2ui/src/less/icons/svg/eye-dropper.svg +4 -0
- package/static/w2ui/src/less/icons/svg/info.svg +8 -0
- package/static/w2ui/src/less/icons/svg/paste.svg +4 -0
- package/static/w2ui/src/less/icons/svg/pencil.svg +5 -0
- package/static/w2ui/src/less/icons/svg/plus.svg +3 -0
- package/static/w2ui/src/less/icons/svg/reload.svg +5 -0
- package/static/w2ui/src/less/icons/svg/search.svg +3 -0
- package/static/w2ui/src/less/icons/svg/settings.svg +8 -0
- package/static/w2ui/src/less/icons/w2ui-font.css +36 -0
- package/static/w2ui/src/less/icons/w2ui-font.woff +0 -0
- package/static/w2ui/src/less/src/buttons.less +184 -0
- package/static/w2ui/src/less/src/common.less +541 -0
- package/static/w2ui/src/less/src/fields.less +302 -0
- package/static/w2ui/src/less/src/form.less +319 -0
- package/static/w2ui/src/less/src/grid.less +1057 -0
- package/static/w2ui/src/less/src/icons.less +37 -0
- package/static/w2ui/src/less/src/layout.less +86 -0
- package/static/w2ui/src/less/src/mixins.less +87 -0
- package/static/w2ui/src/less/src/popup.less +277 -0
- package/static/w2ui/src/less/src/sidebar.less +343 -0
- package/static/w2ui/src/less/src/tabs.less +145 -0
- package/static/w2ui/src/less/src/toolbar.less +219 -0
- package/static/w2ui/src/less/src/tooltip.less +948 -0
- package/static/w2ui/src/less/w2ui.less +196 -0
- package/static/w2ui/src/locale/az-az.json +114 -0
- package/static/w2ui/src/locale/ba-ba.json +114 -0
- package/static/w2ui/src/locale/bg-bg.json +114 -0
- package/static/w2ui/src/locale/ca-es.json +114 -0
- package/static/w2ui/src/locale/da-dk.json +114 -0
- package/static/w2ui/src/locale/de-de.json +114 -0
- package/static/w2ui/src/locale/en-gb.json +17 -0
- package/static/w2ui/src/locale/en-us.json +17 -0
- package/static/w2ui/src/locale/es-ar.json +115 -0
- package/static/w2ui/src/locale/es-cr.json +119 -0
- package/static/w2ui/src/locale/es-es.json +114 -0
- package/static/w2ui/src/locale/es-mx.json +114 -0
- package/static/w2ui/src/locale/fr-fr.json +114 -0
- package/static/w2ui/src/locale/gl-es.json +114 -0
- package/static/w2ui/src/locale/hr-hr.json +114 -0
- package/static/w2ui/src/locale/hu-hu.json +114 -0
- package/static/w2ui/src/locale/id-id.json +114 -0
- package/static/w2ui/src/locale/it-it.json +114 -0
- package/static/w2ui/src/locale/ja-jp.json +114 -0
- package/static/w2ui/src/locale/kk-kz.json +116 -0
- package/static/w2ui/src/locale/ko-kr.json +114 -0
- package/static/w2ui/src/locale/lt-lt.json +114 -0
- package/static/w2ui/src/locale/nl-nl.json +114 -0
- package/static/w2ui/src/locale/no-no.json +114 -0
- package/static/w2ui/src/locale/pl-pl.json +114 -0
- package/static/w2ui/src/locale/pt-br.json +114 -0
- package/static/w2ui/src/locale/ru-ru.json +116 -0
- package/static/w2ui/src/locale/sk-sk.json +114 -0
- package/static/w2ui/src/locale/sl-si.json +116 -0
- package/static/w2ui/src/locale/sr-rs.json +114 -0
- package/static/w2ui/src/locale/tr-tr.json +114 -0
- package/static/w2ui/src/locale/uk-ua.json +114 -0
- package/static/w2ui/src/locale/zh-cn.json +114 -0
- package/static/w2ui/src/locale/zh-tw.json +114 -0
- package/static/w2ui/src/query.js +583 -0
- package/static/w2ui/src/readme.md +11 -0
- package/static/w2ui/src/w2base.js +311 -0
- package/static/w2ui/src/w2compat.js +207 -0
- package/static/w2ui/src/w2field.js +1854 -0
- package/static/w2ui/src/w2form.js +2411 -0
- package/static/w2ui/src/w2grid.js +8916 -0
- package/static/w2ui/src/w2layout.js +1194 -0
- package/static/w2ui/src/w2locale.js +129 -0
- package/static/w2ui/src/w2popup.js +909 -0
- package/static/w2ui/src/w2sidebar.js +1769 -0
- package/static/w2ui/src/w2tabs.js +669 -0
- package/static/w2ui/src/w2toolbar.js +1180 -0
- package/static/w2ui/src/w2tooltip.js +3134 -0
- package/static/w2ui/src/w2utils.js +2457 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
{
|
|
4
|
+
const Emitter = typeof window.Emitter === 'undefined' ? class Emitter {
|
|
5
|
+
constructor(eventListenerMap = {}) {
|
|
6
|
+
this.events = {};
|
|
7
|
+
for(const name in eventListenerMap){
|
|
8
|
+
this.on(name,eventListenerMap[name]);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
on(name, callback) {
|
|
12
|
+
this.events[name] = this.events[name] || [];
|
|
13
|
+
this.events[name].push(callback);
|
|
14
|
+
}
|
|
15
|
+
once(name, callback) {
|
|
16
|
+
callback.once = true;
|
|
17
|
+
this.on(name, callback);
|
|
18
|
+
}
|
|
19
|
+
emit(name, ...data) {
|
|
20
|
+
if (this.events[name] === undefined ) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
for (const c of [...this.events[name]]) {
|
|
24
|
+
c(...data);
|
|
25
|
+
if (c.once) {
|
|
26
|
+
const index = this.events[name].indexOf(c);
|
|
27
|
+
this.events[name].splice(index, 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} : window.Emitter;
|
|
32
|
+
|
|
33
|
+
class SimpleTree extends Emitter {
|
|
34
|
+
constructor(parent, properties = {}) {
|
|
35
|
+
super();
|
|
36
|
+
// do not toggle with click
|
|
37
|
+
parent.addEventListener('click', e => {
|
|
38
|
+
// e.clientX to prevent stopping Enter key
|
|
39
|
+
// e.detail to prevent dbl-click
|
|
40
|
+
// e.offsetX to allow plus and minus clicking
|
|
41
|
+
if (e && e.clientX && e.detail === 1 && e.offsetX >= 0) {
|
|
42
|
+
return e.preventDefault();
|
|
43
|
+
}
|
|
44
|
+
const active = this.active();
|
|
45
|
+
if (active && active.dataset.type === SimpleTree.FILE) {
|
|
46
|
+
e.preventDefault();
|
|
47
|
+
this.emit('action', active);
|
|
48
|
+
if (properties['no-focus-on-action'] === true) {
|
|
49
|
+
window.clearTimeout(this.id);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
parent.classList.add('simple-tree');
|
|
54
|
+
if (properties.dark) {
|
|
55
|
+
parent.classList.add('dark');
|
|
56
|
+
}
|
|
57
|
+
this.parent = parent.appendChild(document.createElement('details'));
|
|
58
|
+
this.parent.appendChild(document.createElement('summary'));
|
|
59
|
+
this.parent.open = true;
|
|
60
|
+
// use this function to alter a node before being passed to this.file or this.folder
|
|
61
|
+
this.interrupt = node => node;
|
|
62
|
+
}
|
|
63
|
+
append(element, parent, before, callback = () => {}) {
|
|
64
|
+
if (before) {
|
|
65
|
+
parent.insertBefore(element, before);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
parent.appendChild(element);
|
|
69
|
+
}
|
|
70
|
+
callback();
|
|
71
|
+
return element;
|
|
72
|
+
}
|
|
73
|
+
remove(element) {
|
|
74
|
+
if (element.dataset.type === SimpleTree.FILE) {
|
|
75
|
+
element.remove();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const parent = element.closest('details');
|
|
79
|
+
parent.remove();
|
|
80
|
+
}
|
|
81
|
+
this.emit('removed', element);
|
|
82
|
+
}
|
|
83
|
+
file(node, parent = this.parent, before) {
|
|
84
|
+
parent = parent.closest('details');
|
|
85
|
+
node = this.interrupt(node);
|
|
86
|
+
const a = this.append(Object.assign(document.createElement('a'), {
|
|
87
|
+
textContent: node.name,
|
|
88
|
+
href: '#'
|
|
89
|
+
}), parent, before);
|
|
90
|
+
a.dataset.type = SimpleTree.FILE;
|
|
91
|
+
this.emit('created', a, node);
|
|
92
|
+
return a;
|
|
93
|
+
}
|
|
94
|
+
folder(node, parent = this.parent, before) {
|
|
95
|
+
parent = parent.closest('details');
|
|
96
|
+
node = this.interrupt(node);
|
|
97
|
+
const details = document.createElement('details');
|
|
98
|
+
const summary = Object.assign(document.createElement('summary'), {
|
|
99
|
+
textContent: node.name
|
|
100
|
+
});
|
|
101
|
+
details.appendChild(summary);
|
|
102
|
+
this.append(details, parent, before, () => {
|
|
103
|
+
details.open = node.open;
|
|
104
|
+
details.dataset.type = SimpleTree.FOLDER;
|
|
105
|
+
});
|
|
106
|
+
this.emit('created', summary, node);
|
|
107
|
+
return summary;
|
|
108
|
+
}
|
|
109
|
+
open(details) {
|
|
110
|
+
details.open = true;
|
|
111
|
+
}
|
|
112
|
+
hierarchy(element = this.active()) {
|
|
113
|
+
if (this.parent.contains(element)) {
|
|
114
|
+
const list = [];
|
|
115
|
+
while (element !== this.parent) {
|
|
116
|
+
if (element.dataset.type === SimpleTree.FILE) {
|
|
117
|
+
list.push(element);
|
|
118
|
+
}
|
|
119
|
+
else if (element.dataset.type === SimpleTree.FOLDER) {
|
|
120
|
+
list.push(element.querySelector('summary'));
|
|
121
|
+
}
|
|
122
|
+
element = element.parentElement;
|
|
123
|
+
}
|
|
124
|
+
return list;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// This method takes an element as an argument and return the full path of it with a custom separator
|
|
131
|
+
getPath(element, separator = '/') {
|
|
132
|
+
const nodes = this.hierarchy(element);
|
|
133
|
+
|
|
134
|
+
return nodes.map(n => n.textContent).reverse().join(separator);
|
|
135
|
+
}
|
|
136
|
+
siblings(element = this.parent.querySelector('a, details')) {
|
|
137
|
+
if (this.parent.contains(element)) {
|
|
138
|
+
if (element.dataset.type === undefined) {
|
|
139
|
+
element = element.parentElement;
|
|
140
|
+
}
|
|
141
|
+
return [...element.parentElement.children].filter(e => {
|
|
142
|
+
return e.dataset.type === SimpleTree.FILE || e.dataset.type === SimpleTree.FOLDER;
|
|
143
|
+
}).map(e => {
|
|
144
|
+
if (e.dataset.type === SimpleTree.FILE) {
|
|
145
|
+
return e;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
return e.querySelector('summary');
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
children(details) {
|
|
157
|
+
const e = details.querySelector('a, details');
|
|
158
|
+
if (e) {
|
|
159
|
+
return this.siblings(e);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
SimpleTree.FILE = 'file';
|
|
167
|
+
SimpleTree.FOLDER = 'folder';
|
|
168
|
+
|
|
169
|
+
class AsyncTree extends SimpleTree {
|
|
170
|
+
constructor(parent, options) {
|
|
171
|
+
super(parent, options);
|
|
172
|
+
// do not allow toggling when folder is loading
|
|
173
|
+
parent.addEventListener('click', e => {
|
|
174
|
+
const details = e.target.parentElement;
|
|
175
|
+
if (details && details.open && details.dataset.loaded === 'false') {
|
|
176
|
+
e.preventDefault();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
parent.classList.add('async-tree');
|
|
180
|
+
}
|
|
181
|
+
// add open event for folder creation
|
|
182
|
+
folder(...args) {
|
|
183
|
+
const summary = super.folder(...args);
|
|
184
|
+
const details = summary.closest('details');
|
|
185
|
+
details.addEventListener('toggle', e => {
|
|
186
|
+
this.emit(details.dataset.loaded === 'false' && details.open ? 'fetch' : 'open', summary);
|
|
187
|
+
});
|
|
188
|
+
summary.resolve = () => {
|
|
189
|
+
details.dataset.loaded = true;
|
|
190
|
+
this.emit('open', summary);
|
|
191
|
+
};
|
|
192
|
+
return summary;
|
|
193
|
+
}
|
|
194
|
+
asyncFolder(node, parent, before) {
|
|
195
|
+
const summary = this.folder(node, parent, before);
|
|
196
|
+
const details = summary.closest('details');
|
|
197
|
+
details.dataset.loaded = false;
|
|
198
|
+
|
|
199
|
+
if (node.open) {
|
|
200
|
+
this.open(details);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return summary;
|
|
204
|
+
}
|
|
205
|
+
unloadFolder(summary) {
|
|
206
|
+
const details = summary.closest('details');
|
|
207
|
+
details.open = false;
|
|
208
|
+
const focused = this.active();
|
|
209
|
+
if (focused && this.parent.contains(focused)) {
|
|
210
|
+
this.select(details);
|
|
211
|
+
}
|
|
212
|
+
[...details.children].slice(1).forEach(e => e.remove());
|
|
213
|
+
details.dataset.loaded = false;
|
|
214
|
+
}
|
|
215
|
+
browse(validate, es = this.siblings()) {
|
|
216
|
+
for (const e of es) {
|
|
217
|
+
if (validate(e)) {
|
|
218
|
+
this.select(e);
|
|
219
|
+
if (e.dataset.type === SimpleTree.FILE) {
|
|
220
|
+
return this.emit('browse', e);
|
|
221
|
+
}
|
|
222
|
+
const parent = e.closest('details');
|
|
223
|
+
if (parent.open) {
|
|
224
|
+
return this.browse(validate, this.children(parent));
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
window.setTimeout(() => {
|
|
228
|
+
this.once('open', () => this.browse(validate, this.children(parent)));
|
|
229
|
+
this.open(parent);
|
|
230
|
+
}, 0);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
this.emit('browse', false);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
class SelectTree extends AsyncTree {
|
|
240
|
+
constructor(parent, options = {}) {
|
|
241
|
+
super(parent, options);
|
|
242
|
+
/* multiple clicks outside of elements */
|
|
243
|
+
parent.addEventListener('click', e => {
|
|
244
|
+
if (e.detail > 1) {
|
|
245
|
+
const active = this.active();
|
|
246
|
+
if (active && active !== e.target) {
|
|
247
|
+
if (e.target.tagName === 'A' || e.target.tagName === 'SUMMARY') {
|
|
248
|
+
return this.select(e.target, 'click');
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (active) {
|
|
252
|
+
this.focus(active);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
window.addEventListener('focus', () => {
|
|
257
|
+
const active = this.active();
|
|
258
|
+
if (active) {
|
|
259
|
+
this.focus(active);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
parent.addEventListener('focusin', e => {
|
|
263
|
+
const active = this.active();
|
|
264
|
+
if (active !== e.target) {
|
|
265
|
+
this.select(e.target, 'focus');
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
this.on('created', (element, node) => {
|
|
269
|
+
if (node.selected) {
|
|
270
|
+
this.select(element);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
parent.classList.add('select-tree');
|
|
274
|
+
// navigate
|
|
275
|
+
if (options.navigate) {
|
|
276
|
+
this.parent.addEventListener("keydown", (e) => {
|
|
277
|
+
const { code } = e;
|
|
278
|
+
if (code === "ArrowUp" || code === "ArrowDown") {
|
|
279
|
+
this.navigate(code === "ArrowUp" ? "backward" : "forward");
|
|
280
|
+
e.preventDefault();
|
|
281
|
+
} else if (code === "ArrowLeft") {
|
|
282
|
+
const element = e.target;
|
|
283
|
+
const { parentElement } = element;
|
|
284
|
+
if (element.dataset.type == "file") {
|
|
285
|
+
parentElement.open = false;
|
|
286
|
+
this.select(parentElement);
|
|
287
|
+
} else {
|
|
288
|
+
if (parentElement.open) parentElement.open = false;
|
|
289
|
+
else if (parentElement.parentElement != this.parent) {
|
|
290
|
+
parentElement.parentElement.open = false;
|
|
291
|
+
this.select(parentElement.parentElement);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
e.preventDefault();
|
|
295
|
+
} else if (code === "ArrowRight") {
|
|
296
|
+
const element = e.target;
|
|
297
|
+
if (element.dataset.type != "file") {
|
|
298
|
+
element.parentElement.open = true;
|
|
299
|
+
const { children } = element.parentElement;
|
|
300
|
+
for(let i = 1;i<children.length;++i){
|
|
301
|
+
const childElement = children[i];
|
|
302
|
+
if(!childElement.hidden){
|
|
303
|
+
this.select(childElement);
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
e.preventDefault();
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
focus(target) {
|
|
314
|
+
window.clearTimeout(this.id);
|
|
315
|
+
this.id = window.setTimeout(() => document.hasFocus() && target.focus(), 100);
|
|
316
|
+
}
|
|
317
|
+
select(target) {
|
|
318
|
+
[...this.parent.querySelectorAll('.selected')].forEach(e => e.classList.remove('selected'));
|
|
319
|
+
if (target) {
|
|
320
|
+
const summary = target.querySelector('summary');
|
|
321
|
+
if (summary) {
|
|
322
|
+
target = summary;
|
|
323
|
+
}
|
|
324
|
+
target.classList.add('selected');
|
|
325
|
+
this.focus(target);
|
|
326
|
+
}
|
|
327
|
+
this.emit('select', target);
|
|
328
|
+
}
|
|
329
|
+
active() {
|
|
330
|
+
return this.parent.querySelector('.selected');
|
|
331
|
+
}
|
|
332
|
+
navigate(direction = 'forward') {
|
|
333
|
+
const e = this.active();
|
|
334
|
+
const list = [...this.parent.querySelectorAll('a, summary')];
|
|
335
|
+
let index = list.indexOf(e);
|
|
336
|
+
if (index === 1 && direction !== 'forward') {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (index === -1 && direction === 'forward') {
|
|
340
|
+
index = 0;
|
|
341
|
+
}
|
|
342
|
+
if (index === -1 && direction !== 'forward') {
|
|
343
|
+
index = list.length;
|
|
344
|
+
}
|
|
345
|
+
const candidates = direction === 'forward' ? list.slice(index + 1) : list.slice(0, index).reverse();
|
|
346
|
+
|
|
347
|
+
for (const m of candidates) {
|
|
348
|
+
// do not select a hidden node
|
|
349
|
+
const ds = this.hierarchy(m).filter(e => e !== m && e.tagName === 'SUMMARY').map(e => e.parentElement);
|
|
350
|
+
if (ds.some(d => d.hidden || d.hasAttribute('open') === false)) {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if(m.parentElement && !m.parentElement.hidden) return this.select(m);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
class JSONTree extends SelectTree {
|
|
359
|
+
json(array, parent) {
|
|
360
|
+
array.forEach(item => {
|
|
361
|
+
if (item.type === SimpleTree.FOLDER) {
|
|
362
|
+
const folder = this[item.asynced ? 'asyncFolder' : 'folder'](item, parent);
|
|
363
|
+
if (item.children) {
|
|
364
|
+
this.json(item.children, folder);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
this.file(item, parent);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
window.Tree = JSONTree;
|
|
374
|
+
}
|