janusweb 1.5.32 → 1.5.36
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/CHANGELOG +39 -0
- package/media/assets/webui/apps/avatar/avatar.js +2 -1
- package/media/assets/webui/apps/buttons/buttons.html +2 -2
- package/media/assets/webui/apps/buttons/buttons.js +2 -2
- package/media/assets/webui/apps/comms/voip.js +2 -4
- package/media/assets/webui/apps/editor/codemirror/addon/hint/javascript-hint.js +162 -0
- package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.css +36 -0
- package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.js +529 -0
- package/media/assets/webui/apps/editor/codemirror/addon/hint/xml-hint.js +140 -0
- package/media/assets/webui/apps/editor/codemirror/keymap/vim.js +5734 -0
- package/media/assets/webui/apps/editor/codemirror/lib/codemirror.css +350 -0
- package/media/assets/webui/apps/editor/codemirror/lib/codemirror.js +9800 -0
- package/media/assets/webui/apps/editor/codemirror/lib/jmldark.css +33 -0
- package/media/assets/webui/apps/editor/codemirror/mode/css/css.js +864 -0
- package/media/assets/webui/apps/editor/codemirror/mode/htmlmixed/htmlmixed.js +153 -0
- package/media/assets/webui/apps/editor/codemirror/mode/javascript/javascript.js +942 -0
- package/media/assets/webui/apps/editor/codemirror/mode/xml/xml.js +413 -0
- package/media/assets/webui/apps/editor/editor.css +3 -0
- package/media/assets/webui/apps/editor/editor.js +407 -9
- package/media/assets/webui/apps/editor/editor.json +6 -3
- package/media/assets/webui/apps/inventory/inventory.js +2 -2
- package/media/assets/webui/apps/locomotion/teleporter.js +8 -7
- package/media/assets/webui/apps/navigation/navigation.js +12 -12
- package/media/assets/webui/apps/vfs/browserfs/browserfs.js +8 -0
- package/media/assets/webui/apps/vfs/vfs.css +52 -0
- package/media/assets/webui/apps/vfs/vfs.js +452 -0
- package/media/assets/webui/apps/vfs/vfs.json +10 -0
- package/media/assets/webui/default.json +2 -1
- package/media/assets/webui/themes/default.css +29 -2
- package/media/lib/physx/physx.release.js +21 -0
- package/media/lib/physx/physx.release.wasm +0 -0
- package/media/manifest.json +5 -5
- package/media/service-worker.js +7 -0
- package/package.json +2 -9
- package/scripts/client.js +65 -45
- package/scripts/config.js +2 -0
- package/scripts/elements/linesegments.js +5 -2
- package/scripts/image.js +7 -1
- package/scripts/janusbase.js +28 -11
- package/scripts/janusghost.js +4 -3
- package/scripts/janusparagraph.js +5 -3
- package/scripts/janusparticle.js +25 -14
- package/scripts/janusplayer.js +25 -10
- package/scripts/janusweb.js +22 -3
- package/scripts/janusxrplayer.js +4 -1
- package/scripts/multiplayermanager.js +3 -3
- package/scripts/object.js +172 -82
- package/scripts/portal.js +12 -10
- package/scripts/room.js +113 -54
- package/scripts/sound.js +0 -1
- package/scripts/text.js +10 -2
- package/scripts/translators/janusvfs.js +20 -0
- package/scripts/video.js +1 -1
- package/scripts/websurface.js +11 -2
- package/utils/build.sh +3 -0
- package/utils/init.sh +1 -1
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2
|
+
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|
3
|
+
|
|
4
|
+
// declare global: DOMRect
|
|
5
|
+
|
|
6
|
+
(function(mod) {
|
|
7
|
+
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
8
|
+
mod(require("../../lib/codemirror"));
|
|
9
|
+
else if (typeof define == "function" && define.amd) // AMD
|
|
10
|
+
define(["../../lib/codemirror"], mod);
|
|
11
|
+
else // Plain browser env
|
|
12
|
+
mod(CodeMirror);
|
|
13
|
+
})(function(CodeMirror) {
|
|
14
|
+
"use strict";
|
|
15
|
+
|
|
16
|
+
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
|
|
17
|
+
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
|
|
18
|
+
|
|
19
|
+
// This is the old interface, kept around for now to stay
|
|
20
|
+
// backwards-compatible.
|
|
21
|
+
CodeMirror.showHint = function(cm, getHints, options) {
|
|
22
|
+
if (!getHints) return cm.showHint(options);
|
|
23
|
+
if (options && options.async) getHints.async = true;
|
|
24
|
+
var newOpts = {hint: getHints};
|
|
25
|
+
if (options) for (var prop in options) newOpts[prop] = options[prop];
|
|
26
|
+
return cm.showHint(newOpts);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
CodeMirror.defineExtension("showHint", function(options) {
|
|
30
|
+
options = parseOptions(this, this.getCursor("start"), options);
|
|
31
|
+
var selections = this.listSelections()
|
|
32
|
+
if (selections.length > 1) return;
|
|
33
|
+
// By default, don't allow completion when something is selected.
|
|
34
|
+
// A hint function can have a `supportsSelection` property to
|
|
35
|
+
// indicate that it can handle selections.
|
|
36
|
+
if (this.somethingSelected()) {
|
|
37
|
+
if (!options.hint.supportsSelection) return;
|
|
38
|
+
// Don't try with cross-line selections
|
|
39
|
+
for (var i = 0; i < selections.length; i++)
|
|
40
|
+
if (selections[i].head.line != selections[i].anchor.line) return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (this.state.completionActive) this.state.completionActive.close();
|
|
44
|
+
var completion = this.state.completionActive = new Completion(this, options);
|
|
45
|
+
if (!completion.options.hint) return;
|
|
46
|
+
|
|
47
|
+
CodeMirror.signal(this, "startCompletion", this);
|
|
48
|
+
completion.update(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
CodeMirror.defineExtension("closeHint", function() {
|
|
52
|
+
if (this.state.completionActive) this.state.completionActive.close()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
function Completion(cm, options) {
|
|
56
|
+
this.cm = cm;
|
|
57
|
+
this.options = options;
|
|
58
|
+
this.widget = null;
|
|
59
|
+
this.debounce = 0;
|
|
60
|
+
this.tick = 0;
|
|
61
|
+
this.startPos = this.cm.getCursor("start");
|
|
62
|
+
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
|
|
63
|
+
|
|
64
|
+
if (this.options.updateOnCursorActivity) {
|
|
65
|
+
var self = this;
|
|
66
|
+
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
|
|
71
|
+
return setTimeout(fn, 1000/60);
|
|
72
|
+
};
|
|
73
|
+
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
|
|
74
|
+
|
|
75
|
+
Completion.prototype = {
|
|
76
|
+
close: function() {
|
|
77
|
+
if (!this.active()) return;
|
|
78
|
+
this.cm.state.completionActive = null;
|
|
79
|
+
this.tick = null;
|
|
80
|
+
if (this.options.updateOnCursorActivity) {
|
|
81
|
+
this.cm.off("cursorActivity", this.activityFunc);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
|
|
85
|
+
if (this.widget) this.widget.close();
|
|
86
|
+
CodeMirror.signal(this.cm, "endCompletion", this.cm);
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
active: function() {
|
|
90
|
+
return this.cm.state.completionActive == this;
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
pick: function(data, i) {
|
|
94
|
+
var completion = data.list[i], self = this;
|
|
95
|
+
this.cm.operation(function() {
|
|
96
|
+
if (completion.hint)
|
|
97
|
+
completion.hint(self.cm, data, completion);
|
|
98
|
+
else
|
|
99
|
+
self.cm.replaceRange(getText(completion), completion.from || data.from,
|
|
100
|
+
completion.to || data.to, "complete");
|
|
101
|
+
CodeMirror.signal(data, "pick", completion);
|
|
102
|
+
self.cm.scrollIntoView();
|
|
103
|
+
});
|
|
104
|
+
if (this.options.closeOnPick) {
|
|
105
|
+
this.close();
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
cursorActivity: function() {
|
|
110
|
+
if (this.debounce) {
|
|
111
|
+
cancelAnimationFrame(this.debounce);
|
|
112
|
+
this.debounce = 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
var identStart = this.startPos;
|
|
116
|
+
if(this.data) {
|
|
117
|
+
identStart = this.data.from;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
|
|
121
|
+
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
|
|
122
|
+
pos.ch < identStart.ch || this.cm.somethingSelected() ||
|
|
123
|
+
(!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
|
|
124
|
+
this.close();
|
|
125
|
+
} else {
|
|
126
|
+
var self = this;
|
|
127
|
+
this.debounce = requestAnimationFrame(function() {self.update();});
|
|
128
|
+
if (this.widget) this.widget.disable();
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
update: function(first) {
|
|
133
|
+
if (this.tick == null) return
|
|
134
|
+
var self = this, myTick = ++this.tick
|
|
135
|
+
fetchHints(this.options.hint, this.cm, this.options, function(data) {
|
|
136
|
+
if (self.tick == myTick) self.finishUpdate(data, first)
|
|
137
|
+
})
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
finishUpdate: function(data, first) {
|
|
141
|
+
if (this.data) CodeMirror.signal(this.data, "update");
|
|
142
|
+
|
|
143
|
+
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
|
|
144
|
+
if (this.widget) this.widget.close();
|
|
145
|
+
|
|
146
|
+
this.data = data;
|
|
147
|
+
|
|
148
|
+
if (data && data.list.length) {
|
|
149
|
+
if (picked && data.list.length == 1) {
|
|
150
|
+
this.pick(data, 0);
|
|
151
|
+
} else {
|
|
152
|
+
this.widget = new Widget(this, data);
|
|
153
|
+
CodeMirror.signal(data, "shown");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
function parseOptions(cm, pos, options) {
|
|
160
|
+
var editor = cm.options.hintOptions;
|
|
161
|
+
var out = {};
|
|
162
|
+
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
|
|
163
|
+
if (editor) for (var prop in editor)
|
|
164
|
+
if (editor[prop] !== undefined) out[prop] = editor[prop];
|
|
165
|
+
if (options) for (var prop in options)
|
|
166
|
+
if (options[prop] !== undefined) out[prop] = options[prop];
|
|
167
|
+
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getText(completion) {
|
|
172
|
+
if (typeof completion == "string") return completion;
|
|
173
|
+
else return completion.text;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function buildKeyMap(completion, handle) {
|
|
177
|
+
var baseMap = {
|
|
178
|
+
Up: function() {handle.moveFocus(-1);},
|
|
179
|
+
Down: function() {handle.moveFocus(1);},
|
|
180
|
+
PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
|
|
181
|
+
PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
|
|
182
|
+
Home: function() {handle.setFocus(0);},
|
|
183
|
+
End: function() {handle.setFocus(handle.length - 1);},
|
|
184
|
+
Enter: handle.pick,
|
|
185
|
+
Tab: handle.pick,
|
|
186
|
+
Esc: handle.close
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
var mac = /Mac/.test(navigator.platform);
|
|
190
|
+
|
|
191
|
+
if (mac) {
|
|
192
|
+
baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);};
|
|
193
|
+
baseMap["Ctrl-N"] = function() {handle.moveFocus(1);};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
var custom = completion.options.customKeys;
|
|
197
|
+
var ourMap = custom ? {} : baseMap;
|
|
198
|
+
function addBinding(key, val) {
|
|
199
|
+
var bound;
|
|
200
|
+
if (typeof val != "string")
|
|
201
|
+
bound = function(cm) { return val(cm, handle); };
|
|
202
|
+
// This mechanism is deprecated
|
|
203
|
+
else if (baseMap.hasOwnProperty(val))
|
|
204
|
+
bound = baseMap[val];
|
|
205
|
+
else
|
|
206
|
+
bound = val;
|
|
207
|
+
ourMap[key] = bound;
|
|
208
|
+
}
|
|
209
|
+
if (custom)
|
|
210
|
+
for (var key in custom) if (custom.hasOwnProperty(key))
|
|
211
|
+
addBinding(key, custom[key]);
|
|
212
|
+
var extra = completion.options.extraKeys;
|
|
213
|
+
if (extra)
|
|
214
|
+
for (var key in extra) if (extra.hasOwnProperty(key))
|
|
215
|
+
addBinding(key, extra[key]);
|
|
216
|
+
return ourMap;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function getHintElement(hintsElement, el) {
|
|
220
|
+
while (el && el != hintsElement) {
|
|
221
|
+
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
|
|
222
|
+
el = el.parentNode;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function Widget(completion, data) {
|
|
227
|
+
this.id = "cm-complete-" + Math.floor(Math.random(1e6))
|
|
228
|
+
this.completion = completion;
|
|
229
|
+
this.data = data;
|
|
230
|
+
this.picked = false;
|
|
231
|
+
var widget = this, cm = completion.cm;
|
|
232
|
+
var ownerDocument = cm.getInputField().ownerDocument;
|
|
233
|
+
var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
|
|
234
|
+
|
|
235
|
+
var hints = this.hints = ownerDocument.createElement("ul");
|
|
236
|
+
hints.setAttribute("role", "listbox")
|
|
237
|
+
hints.setAttribute("aria-expanded", "true")
|
|
238
|
+
hints.id = this.id
|
|
239
|
+
var theme = completion.cm.options.theme;
|
|
240
|
+
hints.className = "CodeMirror-hints " + theme;
|
|
241
|
+
this.selectedHint = data.selectedHint || 0;
|
|
242
|
+
|
|
243
|
+
var completions = data.list;
|
|
244
|
+
for (var i = 0; i < completions.length; ++i) {
|
|
245
|
+
var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i];
|
|
246
|
+
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
|
|
247
|
+
if (cur.className != null) className = cur.className + " " + className;
|
|
248
|
+
elt.className = className;
|
|
249
|
+
if (i == this.selectedHint) elt.setAttribute("aria-selected", "true")
|
|
250
|
+
elt.id = this.id + "-" + i
|
|
251
|
+
elt.setAttribute("role", "option")
|
|
252
|
+
if (cur.render) cur.render(elt, data, cur);
|
|
253
|
+
else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
|
|
254
|
+
elt.hintId = i;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
var container = completion.options.container || ownerDocument.body;
|
|
258
|
+
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
|
|
259
|
+
var left = pos.left, top = pos.bottom, below = true;
|
|
260
|
+
var offsetLeft = 0, offsetTop = 0;
|
|
261
|
+
if (container !== ownerDocument.body) {
|
|
262
|
+
// We offset the cursor position because left and top are relative to the offsetParent's top left corner.
|
|
263
|
+
var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
|
|
264
|
+
var offsetParent = isContainerPositioned ? container : container.offsetParent;
|
|
265
|
+
var offsetParentPosition = offsetParent.getBoundingClientRect();
|
|
266
|
+
var bodyPosition = ownerDocument.body.getBoundingClientRect();
|
|
267
|
+
offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
|
|
268
|
+
offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
|
|
269
|
+
}
|
|
270
|
+
hints.style.left = (left - offsetLeft) + "px";
|
|
271
|
+
hints.style.top = (top - offsetTop) + "px";
|
|
272
|
+
|
|
273
|
+
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
|
|
274
|
+
var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
|
|
275
|
+
var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
|
|
276
|
+
container.appendChild(hints);
|
|
277
|
+
cm.getInputField().setAttribute("aria-autocomplete", "list")
|
|
278
|
+
cm.getInputField().setAttribute("aria-owns", this.id)
|
|
279
|
+
cm.getInputField().setAttribute("aria-activedescendant", this.id + "-" + this.selectedHint)
|
|
280
|
+
|
|
281
|
+
var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect();
|
|
282
|
+
var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false;
|
|
283
|
+
|
|
284
|
+
// Compute in the timeout to avoid reflow on init
|
|
285
|
+
var startScroll;
|
|
286
|
+
setTimeout(function() { startScroll = cm.getScrollInfo(); });
|
|
287
|
+
|
|
288
|
+
var overlapY = box.bottom - winH;
|
|
289
|
+
if (overlapY > 0) {
|
|
290
|
+
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
|
|
291
|
+
if (curTop - height > 0) { // Fits above cursor
|
|
292
|
+
hints.style.top = (top = pos.top - height - offsetTop) + "px";
|
|
293
|
+
below = false;
|
|
294
|
+
} else if (height > winH) {
|
|
295
|
+
hints.style.height = (winH - 5) + "px";
|
|
296
|
+
hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px";
|
|
297
|
+
var cursor = cm.getCursor();
|
|
298
|
+
if (data.from.ch != cursor.ch) {
|
|
299
|
+
pos = cm.cursorCoords(cursor);
|
|
300
|
+
hints.style.left = (left = pos.left - offsetLeft) + "px";
|
|
301
|
+
box = hints.getBoundingClientRect();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
var overlapX = box.right - winW;
|
|
306
|
+
if (scrolls) overlapX += cm.display.nativeBarWidth;
|
|
307
|
+
if (overlapX > 0) {
|
|
308
|
+
if (box.right - box.left > winW) {
|
|
309
|
+
hints.style.width = (winW - 5) + "px";
|
|
310
|
+
overlapX -= (box.right - box.left) - winW;
|
|
311
|
+
}
|
|
312
|
+
hints.style.left = (left = pos.left - overlapX - offsetLeft) + "px";
|
|
313
|
+
}
|
|
314
|
+
if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
|
|
315
|
+
node.style.paddingRight = cm.display.nativeBarWidth + "px"
|
|
316
|
+
|
|
317
|
+
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
|
|
318
|
+
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
|
|
319
|
+
setFocus: function(n) { widget.changeActive(n); },
|
|
320
|
+
menuSize: function() { return widget.screenAmount(); },
|
|
321
|
+
length: completions.length,
|
|
322
|
+
close: function() { completion.close(); },
|
|
323
|
+
pick: function() { widget.pick(); },
|
|
324
|
+
data: data
|
|
325
|
+
}));
|
|
326
|
+
|
|
327
|
+
if (completion.options.closeOnUnfocus) {
|
|
328
|
+
var closingOnBlur;
|
|
329
|
+
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
|
|
330
|
+
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
cm.on("scroll", this.onScroll = function() {
|
|
334
|
+
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
|
|
335
|
+
if (!startScroll) startScroll = cm.getScrollInfo();
|
|
336
|
+
var newTop = top + startScroll.top - curScroll.top;
|
|
337
|
+
var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
|
|
338
|
+
if (!below) point += hints.offsetHeight;
|
|
339
|
+
if (point <= editor.top || point >= editor.bottom) return completion.close();
|
|
340
|
+
hints.style.top = newTop + "px";
|
|
341
|
+
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
CodeMirror.on(hints, "dblclick", function(e) {
|
|
345
|
+
var t = getHintElement(hints, e.target || e.srcElement);
|
|
346
|
+
if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
CodeMirror.on(hints, "click", function(e) {
|
|
350
|
+
var t = getHintElement(hints, e.target || e.srcElement);
|
|
351
|
+
if (t && t.hintId != null) {
|
|
352
|
+
widget.changeActive(t.hintId);
|
|
353
|
+
if (completion.options.completeOnSingleClick) widget.pick();
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
CodeMirror.on(hints, "mousedown", function() {
|
|
358
|
+
setTimeout(function(){cm.focus();}, 20);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// The first hint doesn't need to be scrolled to on init
|
|
362
|
+
var selectedHintRange = this.getSelectedHintRange();
|
|
363
|
+
if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
|
|
364
|
+
this.scrollToActive();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
Widget.prototype = {
|
|
372
|
+
close: function() {
|
|
373
|
+
if (this.completion.widget != this) return;
|
|
374
|
+
this.completion.widget = null;
|
|
375
|
+
if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints);
|
|
376
|
+
this.completion.cm.removeKeyMap(this.keyMap);
|
|
377
|
+
var input = this.completion.cm.getInputField()
|
|
378
|
+
input.removeAttribute("aria-activedescendant")
|
|
379
|
+
input.removeAttribute("aria-owns")
|
|
380
|
+
|
|
381
|
+
var cm = this.completion.cm;
|
|
382
|
+
if (this.completion.options.closeOnUnfocus) {
|
|
383
|
+
cm.off("blur", this.onBlur);
|
|
384
|
+
cm.off("focus", this.onFocus);
|
|
385
|
+
}
|
|
386
|
+
cm.off("scroll", this.onScroll);
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
disable: function() {
|
|
390
|
+
this.completion.cm.removeKeyMap(this.keyMap);
|
|
391
|
+
var widget = this;
|
|
392
|
+
this.keyMap = {Enter: function() { widget.picked = true; }};
|
|
393
|
+
this.completion.cm.addKeyMap(this.keyMap);
|
|
394
|
+
},
|
|
395
|
+
|
|
396
|
+
pick: function() {
|
|
397
|
+
this.completion.pick(this.data, this.selectedHint);
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
changeActive: function(i, avoidWrap) {
|
|
401
|
+
if (i >= this.data.list.length)
|
|
402
|
+
i = avoidWrap ? this.data.list.length - 1 : 0;
|
|
403
|
+
else if (i < 0)
|
|
404
|
+
i = avoidWrap ? 0 : this.data.list.length - 1;
|
|
405
|
+
if (this.selectedHint == i) return;
|
|
406
|
+
var node = this.hints.childNodes[this.selectedHint];
|
|
407
|
+
if (node) {
|
|
408
|
+
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
|
|
409
|
+
node.removeAttribute("aria-selected")
|
|
410
|
+
}
|
|
411
|
+
node = this.hints.childNodes[this.selectedHint = i];
|
|
412
|
+
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
|
|
413
|
+
node.setAttribute("aria-selected", "true")
|
|
414
|
+
this.completion.cm.getInputField().setAttribute("aria-activedescendant", node.id)
|
|
415
|
+
this.scrollToActive()
|
|
416
|
+
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
|
|
417
|
+
},
|
|
418
|
+
|
|
419
|
+
scrollToActive: function() {
|
|
420
|
+
var selectedHintRange = this.getSelectedHintRange();
|
|
421
|
+
var node1 = this.hints.childNodes[selectedHintRange.from];
|
|
422
|
+
var node2 = this.hints.childNodes[selectedHintRange.to];
|
|
423
|
+
var firstNode = this.hints.firstChild;
|
|
424
|
+
if (node1.offsetTop < this.hints.scrollTop)
|
|
425
|
+
this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
|
|
426
|
+
else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
|
|
427
|
+
this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
screenAmount: function() {
|
|
431
|
+
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
getSelectedHintRange: function() {
|
|
435
|
+
var margin = this.completion.options.scrollMargin || 0;
|
|
436
|
+
return {
|
|
437
|
+
from: Math.max(0, this.selectedHint - margin),
|
|
438
|
+
to: Math.min(this.data.list.length - 1, this.selectedHint + margin),
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
function applicableHelpers(cm, helpers) {
|
|
444
|
+
if (!cm.somethingSelected()) return helpers
|
|
445
|
+
var result = []
|
|
446
|
+
for (var i = 0; i < helpers.length; i++)
|
|
447
|
+
if (helpers[i].supportsSelection) result.push(helpers[i])
|
|
448
|
+
return result
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function fetchHints(hint, cm, options, callback) {
|
|
452
|
+
if (hint.async) {
|
|
453
|
+
hint(cm, callback, options)
|
|
454
|
+
} else {
|
|
455
|
+
var result = hint(cm, options)
|
|
456
|
+
if (result && result.then) result.then(callback)
|
|
457
|
+
else callback(result)
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function resolveAutoHints(cm, pos) {
|
|
462
|
+
var helpers = cm.getHelpers(pos, "hint"), words
|
|
463
|
+
if (helpers.length) {
|
|
464
|
+
var resolved = function(cm, callback, options) {
|
|
465
|
+
var app = applicableHelpers(cm, helpers);
|
|
466
|
+
function run(i) {
|
|
467
|
+
if (i == app.length) return callback(null)
|
|
468
|
+
fetchHints(app[i], cm, options, function(result) {
|
|
469
|
+
if (result && result.list.length > 0) callback(result)
|
|
470
|
+
else run(i + 1)
|
|
471
|
+
})
|
|
472
|
+
}
|
|
473
|
+
run(0)
|
|
474
|
+
}
|
|
475
|
+
resolved.async = true
|
|
476
|
+
resolved.supportsSelection = true
|
|
477
|
+
return resolved
|
|
478
|
+
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
|
|
479
|
+
return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
|
|
480
|
+
} else if (CodeMirror.hint.anyword) {
|
|
481
|
+
return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
|
|
482
|
+
} else {
|
|
483
|
+
return function() {}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
CodeMirror.registerHelper("hint", "auto", {
|
|
488
|
+
resolve: resolveAutoHints
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
|
|
492
|
+
var cur = cm.getCursor(), token = cm.getTokenAt(cur)
|
|
493
|
+
var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
|
|
494
|
+
if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
|
|
495
|
+
term = token.string.substr(0, cur.ch - token.start)
|
|
496
|
+
} else {
|
|
497
|
+
term = ""
|
|
498
|
+
from = cur
|
|
499
|
+
}
|
|
500
|
+
var found = [];
|
|
501
|
+
for (var i = 0; i < options.words.length; i++) {
|
|
502
|
+
var word = options.words[i];
|
|
503
|
+
if (word.slice(0, term.length) == term)
|
|
504
|
+
found.push(word);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if (found.length) return {list: found, from: from, to: to};
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
CodeMirror.commands.autocomplete = CodeMirror.showHint;
|
|
511
|
+
|
|
512
|
+
var defaultOptions = {
|
|
513
|
+
hint: CodeMirror.hint.auto,
|
|
514
|
+
completeSingle: true,
|
|
515
|
+
alignWithWord: true,
|
|
516
|
+
closeCharacters: /[\s()\[\]{};:>,]/,
|
|
517
|
+
closeOnPick: true,
|
|
518
|
+
closeOnUnfocus: true,
|
|
519
|
+
updateOnCursorActivity: true,
|
|
520
|
+
completeOnSingleClick: true,
|
|
521
|
+
container: null,
|
|
522
|
+
customKeys: null,
|
|
523
|
+
extraKeys: null,
|
|
524
|
+
paddingForScrollbar: true,
|
|
525
|
+
moveOnOverlap: true,
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
CodeMirror.defineOption("hintOptions", null);
|
|
529
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2
|
+
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
|
3
|
+
|
|
4
|
+
(function(mod) {
|
|
5
|
+
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
6
|
+
mod(require("../../lib/codemirror"));
|
|
7
|
+
else if (typeof define == "function" && define.amd) // AMD
|
|
8
|
+
define(["../../lib/codemirror"], mod);
|
|
9
|
+
else // Plain browser env
|
|
10
|
+
mod(CodeMirror);
|
|
11
|
+
})(function(CodeMirror) {
|
|
12
|
+
"use strict";
|
|
13
|
+
|
|
14
|
+
var Pos = CodeMirror.Pos;
|
|
15
|
+
|
|
16
|
+
function matches(hint, typed, matchInMiddle) {
|
|
17
|
+
if (matchInMiddle) return hint.indexOf(typed) >= 0;
|
|
18
|
+
else return hint.lastIndexOf(typed, 0) == 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getHints(cm, options) {
|
|
22
|
+
var tags = options && options.schemaInfo;
|
|
23
|
+
var quote = (options && options.quoteChar) || '"';
|
|
24
|
+
var matchInMiddle = options && options.matchInMiddle;
|
|
25
|
+
if (!tags) return;
|
|
26
|
+
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
|
|
27
|
+
if (token.end > cur.ch) {
|
|
28
|
+
token.end = cur.ch;
|
|
29
|
+
token.string = token.string.slice(0, cur.ch - token.start);
|
|
30
|
+
}
|
|
31
|
+
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
|
|
32
|
+
if (!inner.mode.xmlCurrentTag) return
|
|
33
|
+
var result = [], replaceToken = false, prefix;
|
|
34
|
+
var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
|
|
35
|
+
var tagName = tag && /^\w/.test(token.string), tagStart;
|
|
36
|
+
|
|
37
|
+
if (tagName) {
|
|
38
|
+
var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
|
|
39
|
+
var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
|
|
40
|
+
if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
|
|
41
|
+
} else if (tag && token.string == "<") {
|
|
42
|
+
tagType = "open";
|
|
43
|
+
} else if (tag && token.string == "</") {
|
|
44
|
+
tagType = "close";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var tagInfo = inner.mode.xmlCurrentTag(inner.state)
|
|
48
|
+
if (!tag && !tagInfo || tagType) {
|
|
49
|
+
if (tagName)
|
|
50
|
+
prefix = token.string;
|
|
51
|
+
replaceToken = tagType;
|
|
52
|
+
var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
|
|
53
|
+
var inner = context.length && context[context.length - 1]
|
|
54
|
+
var curTag = inner && tags[inner]
|
|
55
|
+
var childList = inner ? curTag && curTag.children : tags["!top"];
|
|
56
|
+
if (childList && tagType != "close") {
|
|
57
|
+
for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
|
|
58
|
+
result.push("<" + childList[i]);
|
|
59
|
+
} else if (tagType != "close") {
|
|
60
|
+
for (var name in tags)
|
|
61
|
+
if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
|
|
62
|
+
result.push("<" + name);
|
|
63
|
+
}
|
|
64
|
+
if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
|
|
65
|
+
result.push("</" + inner + ">");
|
|
66
|
+
} else {
|
|
67
|
+
// Attribute completion
|
|
68
|
+
var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs, attrDelims = curTag && curTag.attrDelims;
|
|
69
|
+
var globalAttrs = tags["!attrs"];
|
|
70
|
+
if (!attrs && !globalAttrs) return;
|
|
71
|
+
if (!attrs) {
|
|
72
|
+
attrs = globalAttrs;
|
|
73
|
+
} else if (globalAttrs) { // Combine tag-local and global attributes
|
|
74
|
+
var set = {};
|
|
75
|
+
for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
|
|
76
|
+
for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
|
|
77
|
+
attrs = set;
|
|
78
|
+
}
|
|
79
|
+
if (token.type == "string" || token.string == "=") { // A value
|
|
80
|
+
var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
|
|
81
|
+
Pos(cur.line, token.type == "string" ? token.start : token.end));
|
|
82
|
+
var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
|
|
83
|
+
if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
|
|
84
|
+
if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
|
|
85
|
+
let atValueDelim = (attrDelims && attrDelims[atName[1]]);
|
|
86
|
+
if (token.type == "string") {
|
|
87
|
+
prefix = token.string;
|
|
88
|
+
var n = 0;
|
|
89
|
+
if (/['"]/.test(token.string.charAt(0))) {
|
|
90
|
+
quote = token.string.charAt(0);
|
|
91
|
+
prefix = token.string.slice(1);
|
|
92
|
+
n++;
|
|
93
|
+
}
|
|
94
|
+
var len = token.string.length;
|
|
95
|
+
if (/['"]/.test(token.string.charAt(len - 1))) {
|
|
96
|
+
quote = token.string.charAt(len - 1);
|
|
97
|
+
prefix = token.string.substr(n, len - 2);
|
|
98
|
+
}
|
|
99
|
+
if (n) { // an opening quote
|
|
100
|
+
var line = cm.getLine(cur.line);
|
|
101
|
+
if (line.length > token.end && line.charAt(token.end) == quote) token.end++; // include a closing quote
|
|
102
|
+
}
|
|
103
|
+
replaceToken = true;
|
|
104
|
+
}
|
|
105
|
+
var returnHintsFromAtValues = function(atValues) {
|
|
106
|
+
let search = prefix,
|
|
107
|
+
preprefix = '';
|
|
108
|
+
if (atValueDelim) {
|
|
109
|
+
let spaceIdx = prefix.lastIndexOf(atValueDelim);
|
|
110
|
+
search = prefix.substr(spaceIdx + 1);
|
|
111
|
+
preprefix = prefix.substr(0, spaceIdx + 1);
|
|
112
|
+
}
|
|
113
|
+
if (atValues)
|
|
114
|
+
for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], search, matchInMiddle))
|
|
115
|
+
result.push(quote + preprefix + atValues[i] + quote);
|
|
116
|
+
return returnHints();
|
|
117
|
+
};
|
|
118
|
+
if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
|
|
119
|
+
return returnHintsFromAtValues(atValues);
|
|
120
|
+
} else { // An attribute name
|
|
121
|
+
if (token.type == "attribute") {
|
|
122
|
+
prefix = token.string;
|
|
123
|
+
replaceToken = true;
|
|
124
|
+
}
|
|
125
|
+
for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || matches(attr, prefix, matchInMiddle)))
|
|
126
|
+
result.push(attr);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function returnHints() {
|
|
130
|
+
return {
|
|
131
|
+
list: result,
|
|
132
|
+
from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
|
|
133
|
+
to: replaceToken ? Pos(cur.line, token.end) : cur
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return returnHints();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
CodeMirror.registerHelper("hint", "xml", getHints);
|
|
140
|
+
});
|