PluginProbe ʕ •ᴥ•ʔ
SiteOrigin CSS / 1.1.1
SiteOrigin CSS v1.1.1
1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.10 1.5.11 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 trunk 1.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0
so-css / lib / codemirror / addon / hint / show-hint.js
so-css / lib / codemirror / addon / hint Last commit date
anyword-hint.js 10 years ago anyword-hint.min.js 9 years ago css-hint.js 11 years ago css-hint.min.js 9 years ago html-hint.js 11 years ago html-hint.min.js 9 years ago javascript-hint.js 11 years ago javascript-hint.min.js 9 years ago show-hint.css 11 years ago show-hint.js 10 years ago show-hint.min.js 9 years ago sql-hint.js 10 years ago sql-hint.min.js 9 years ago xml-hint.js 11 years ago xml-hint.min.js 10 years ago
show-hint.js
441 lines
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 // Distributed under an MIT license: http://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 HINT_ELEMENT_CLASS = "CodeMirror-hint";
15 var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
16
17 // This is the old interface, kept around for now to stay
18 // backwards-compatible.
19 CodeMirror.showHint = function(cm, getHints, options) {
20 if (!getHints) return cm.showHint(options);
21 if (options && options.async) getHints.async = true;
22 var newOpts = {hint: getHints};
23 if (options) for (var prop in options) newOpts[prop] = options[prop];
24 return cm.showHint(newOpts);
25 };
26
27 CodeMirror.defineExtension("showHint", function(options) {
28 options = parseOptions(this, this.getCursor("start"), options);
29 var selections = this.listSelections()
30 if (selections.length > 1) return;
31 // By default, don't allow completion when something is selected.
32 // A hint function can have a `supportsSelection` property to
33 // indicate that it can handle selections.
34 if (this.somethingSelected()) {
35 if (!options.hint.supportsSelection) return;
36 // Don't try with cross-line selections
37 for (var i = 0; i < selections.length; i++)
38 if (selections[i].head.line != selections[i].anchor.line) return;
39 }
40
41 if (this.state.completionActive) this.state.completionActive.close();
42 var completion = this.state.completionActive = new Completion(this, options);
43 if (!completion.options.hint) return;
44
45 CodeMirror.signal(this, "startCompletion", this);
46 completion.update(true);
47 });
48
49 function Completion(cm, options) {
50 this.cm = cm;
51 this.options = options;
52 this.widget = null;
53 this.debounce = 0;
54 this.tick = 0;
55 this.startPos = this.cm.getCursor("start");
56 this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
57
58 var self = this;
59 cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
60 }
61
62 var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
63 return setTimeout(fn, 1000/60);
64 };
65 var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
66
67 Completion.prototype = {
68 close: function() {
69 if (!this.active()) return;
70 this.cm.state.completionActive = null;
71 this.tick = null;
72 this.cm.off("cursorActivity", this.activityFunc);
73
74 if (this.widget && this.data) CodeMirror.signal(this.data, "close");
75 if (this.widget) this.widget.close();
76 CodeMirror.signal(this.cm, "endCompletion", this.cm);
77 },
78
79 active: function() {
80 return this.cm.state.completionActive == this;
81 },
82
83 pick: function(data, i) {
84 var completion = data.list[i];
85 if (completion.hint) completion.hint(this.cm, data, completion);
86 else this.cm.replaceRange(getText(completion), completion.from || data.from,
87 completion.to || data.to, "complete");
88 CodeMirror.signal(data, "pick", completion);
89 this.close();
90 },
91
92 cursorActivity: function() {
93 if (this.debounce) {
94 cancelAnimationFrame(this.debounce);
95 this.debounce = 0;
96 }
97
98 var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
99 if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
100 pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
101 (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
102 this.close();
103 } else {
104 var self = this;
105 this.debounce = requestAnimationFrame(function() {self.update();});
106 if (this.widget) this.widget.disable();
107 }
108 },
109
110 update: function(first) {
111 if (this.tick == null) return;
112 if (!this.options.hint.async) {
113 this.finishUpdate(this.options.hint(this.cm, this.options), first);
114 } else {
115 var myTick = ++this.tick, self = this;
116 this.options.hint(this.cm, function(data) {
117 if (self.tick == myTick) self.finishUpdate(data, first);
118 }, this.options);
119 }
120 },
121
122 finishUpdate: function(data, first) {
123 if (this.data) CodeMirror.signal(this.data, "update");
124 if (data && this.data && CodeMirror.cmpPos(data.from, this.data.from)) data = null;
125 this.data = data;
126
127 var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
128 if (this.widget) this.widget.close();
129 if (data && data.list.length) {
130 if (picked && data.list.length == 1) {
131 this.pick(data, 0);
132 } else {
133 this.widget = new Widget(this, data);
134 CodeMirror.signal(data, "shown");
135 }
136 }
137 }
138 };
139
140 function parseOptions(cm, pos, options) {
141 var editor = cm.options.hintOptions;
142 var out = {};
143 for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
144 if (editor) for (var prop in editor)
145 if (editor[prop] !== undefined) out[prop] = editor[prop];
146 if (options) for (var prop in options)
147 if (options[prop] !== undefined) out[prop] = options[prop];
148 if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
149 return out;
150 }
151
152 function getText(completion) {
153 if (typeof completion == "string") return completion;
154 else return completion.text;
155 }
156
157 function buildKeyMap(completion, handle) {
158 var baseMap = {
159 Up: function() {handle.moveFocus(-1);},
160 Down: function() {handle.moveFocus(1);},
161 PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
162 PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
163 Home: function() {handle.setFocus(0);},
164 End: function() {handle.setFocus(handle.length - 1);},
165 Enter: handle.pick,
166 Tab: handle.pick,
167 Esc: handle.close
168 };
169 var custom = completion.options.customKeys;
170 var ourMap = custom ? {} : baseMap;
171 function addBinding(key, val) {
172 var bound;
173 if (typeof val != "string")
174 bound = function(cm) { return val(cm, handle); };
175 // This mechanism is deprecated
176 else if (baseMap.hasOwnProperty(val))
177 bound = baseMap[val];
178 else
179 bound = val;
180 ourMap[key] = bound;
181 }
182 if (custom)
183 for (var key in custom) if (custom.hasOwnProperty(key))
184 addBinding(key, custom[key]);
185 var extra = completion.options.extraKeys;
186 if (extra)
187 for (var key in extra) if (extra.hasOwnProperty(key))
188 addBinding(key, extra[key]);
189 return ourMap;
190 }
191
192 function getHintElement(hintsElement, el) {
193 while (el && el != hintsElement) {
194 if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
195 el = el.parentNode;
196 }
197 }
198
199 function Widget(completion, data) {
200 this.completion = completion;
201 this.data = data;
202 this.picked = false;
203 var widget = this, cm = completion.cm;
204
205 var hints = this.hints = document.createElement("ul");
206 hints.className = "CodeMirror-hints";
207 this.selectedHint = data.selectedHint || 0;
208
209 var completions = data.list;
210 for (var i = 0; i < completions.length; ++i) {
211 var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
212 var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
213 if (cur.className != null) className = cur.className + " " + className;
214 elt.className = className;
215 if (cur.render) cur.render(elt, data, cur);
216 else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
217 elt.hintId = i;
218 }
219
220 var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
221 var left = pos.left, top = pos.bottom, below = true;
222 hints.style.left = left + "px";
223 hints.style.top = top + "px";
224 // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
225 var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
226 var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
227 (completion.options.container || document.body).appendChild(hints);
228 var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
229 if (overlapY > 0) {
230 var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
231 if (curTop - height > 0) { // Fits above cursor
232 hints.style.top = (top = pos.top - height) + "px";
233 below = false;
234 } else if (height > winH) {
235 hints.style.height = (winH - 5) + "px";
236 hints.style.top = (top = pos.bottom - box.top) + "px";
237 var cursor = cm.getCursor();
238 if (data.from.ch != cursor.ch) {
239 pos = cm.cursorCoords(cursor);
240 hints.style.left = (left = pos.left) + "px";
241 box = hints.getBoundingClientRect();
242 }
243 }
244 }
245 var overlapX = box.right - winW;
246 if (overlapX > 0) {
247 if (box.right - box.left > winW) {
248 hints.style.width = (winW - 5) + "px";
249 overlapX -= (box.right - box.left) - winW;
250 }
251 hints.style.left = (left = pos.left - overlapX) + "px";
252 }
253
254 cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
255 moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
256 setFocus: function(n) { widget.changeActive(n); },
257 menuSize: function() { return widget.screenAmount(); },
258 length: completions.length,
259 close: function() { completion.close(); },
260 pick: function() { widget.pick(); },
261 data: data
262 }));
263
264 if (completion.options.closeOnUnfocus) {
265 var closingOnBlur;
266 cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
267 cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
268 }
269
270 var startScroll = cm.getScrollInfo();
271 cm.on("scroll", this.onScroll = function() {
272 var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
273 var newTop = top + startScroll.top - curScroll.top;
274 var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
275 if (!below) point += hints.offsetHeight;
276 if (point <= editor.top || point >= editor.bottom) return completion.close();
277 hints.style.top = newTop + "px";
278 hints.style.left = (left + startScroll.left - curScroll.left) + "px";
279 });
280
281 CodeMirror.on(hints, "dblclick", function(e) {
282 var t = getHintElement(hints, e.target || e.srcElement);
283 if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
284 });
285
286 CodeMirror.on(hints, "click", function(e) {
287 var t = getHintElement(hints, e.target || e.srcElement);
288 if (t && t.hintId != null) {
289 widget.changeActive(t.hintId);
290 if (completion.options.completeOnSingleClick) widget.pick();
291 }
292 });
293
294 CodeMirror.on(hints, "mousedown", function() {
295 setTimeout(function(){cm.focus();}, 20);
296 });
297
298 CodeMirror.signal(data, "select", completions[0], hints.firstChild);
299 return true;
300 }
301
302 Widget.prototype = {
303 close: function() {
304 if (this.completion.widget != this) return;
305 this.completion.widget = null;
306 this.hints.parentNode.removeChild(this.hints);
307 this.completion.cm.removeKeyMap(this.keyMap);
308
309 var cm = this.completion.cm;
310 if (this.completion.options.closeOnUnfocus) {
311 cm.off("blur", this.onBlur);
312 cm.off("focus", this.onFocus);
313 }
314 cm.off("scroll", this.onScroll);
315 },
316
317 disable: function() {
318 this.completion.cm.removeKeyMap(this.keyMap);
319 var widget = this;
320 this.keyMap = {Enter: function() { widget.picked = true; }};
321 this.completion.cm.addKeyMap(this.keyMap);
322 },
323
324 pick: function() {
325 this.completion.pick(this.data, this.selectedHint);
326 },
327
328 changeActive: function(i, avoidWrap) {
329 if (i >= this.data.list.length)
330 i = avoidWrap ? this.data.list.length - 1 : 0;
331 else if (i < 0)
332 i = avoidWrap ? 0 : this.data.list.length - 1;
333 if (this.selectedHint == i) return;
334 var node = this.hints.childNodes[this.selectedHint];
335 node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
336 node = this.hints.childNodes[this.selectedHint = i];
337 node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
338 if (node.offsetTop < this.hints.scrollTop)
339 this.hints.scrollTop = node.offsetTop - 3;
340 else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
341 this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
342 CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
343 },
344
345 screenAmount: function() {
346 return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
347 }
348 };
349
350 function applicableHelpers(cm, helpers) {
351 if (!cm.somethingSelected()) return helpers
352 var result = []
353 for (var i = 0; i < helpers.length; i++)
354 if (helpers[i].supportsSelection) result.push(helpers[i])
355 return result
356 }
357
358 function resolveAutoHints(cm, pos) {
359 var helpers = cm.getHelpers(pos, "hint"), words
360 if (helpers.length) {
361 var async = false, resolved
362 for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true
363 if (async) {
364 resolved = function(cm, callback, options) {
365 var app = applicableHelpers(cm, helpers)
366 function run(i, result) {
367 if (i == app.length) return callback(null)
368 var helper = app[i]
369 if (helper.async) {
370 helper(cm, function(result) {
371 if (result) callback(result)
372 else run(i + 1)
373 }, options)
374 } else {
375 var result = helper(cm, options)
376 if (result) callback(result)
377 else run(i + 1)
378 }
379 }
380 run(0)
381 }
382 resolved.async = true
383 } else {
384 resolved = function(cm, options) {
385 var app = applicableHelpers(cm, helpers)
386 for (var i = 0; i < app.length; i++) {
387 var cur = app[i](cm, options)
388 if (cur && cur.list.length) return cur
389 }
390 }
391 }
392 resolved.supportsSelection = true
393 return resolved
394 } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
395 return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
396 } else if (CodeMirror.hint.anyword) {
397 return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
398 } else {
399 return function() {}
400 }
401 }
402
403 CodeMirror.registerHelper("hint", "auto", {
404 resolve: resolveAutoHints
405 });
406
407 CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
408 var cur = cm.getCursor(), token = cm.getTokenAt(cur);
409 var to = CodeMirror.Pos(cur.line, token.end);
410 if (token.string && /\w/.test(token.string[token.string.length - 1])) {
411 var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
412 } else {
413 var term = "", from = to;
414 }
415 var found = [];
416 for (var i = 0; i < options.words.length; i++) {
417 var word = options.words[i];
418 if (word.slice(0, term.length) == term)
419 found.push(word);
420 }
421
422 if (found.length) return {list: found, from: from, to: to};
423 });
424
425 CodeMirror.commands.autocomplete = CodeMirror.showHint;
426
427 var defaultOptions = {
428 hint: CodeMirror.hint.auto,
429 completeSingle: true,
430 alignWithWord: true,
431 closeCharacters: /[\s()\[\]{};:>,]/,
432 closeOnUnfocus: true,
433 completeOnSingleClick: true,
434 container: null,
435 customKeys: null,
436 extraKeys: null
437 };
438
439 CodeMirror.defineOption("hintOptions", null);
440 });
441