]>
Commit | Line | Data |
---|---|---|
06a3d686 BB |
1 | (function() { |
2 | CodeMirror.simpleHint = function(editor, getHints, givenOptions) { | |
3 | // Determine effective options based on given values and defaults. | |
4 | var options = {}, defaults = CodeMirror.simpleHint.defaults; | |
5 | for (var opt in defaults) | |
6 | if (defaults.hasOwnProperty(opt)) | |
7 | options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt]; | |
8 | ||
9 | function collectHints(previousToken) { | |
10 | // We want a single cursor position. | |
11 | if (editor.somethingSelected()) return; | |
12 | ||
13 | var tempToken = editor.getTokenAt(editor.getCursor()); | |
14 | ||
15 | // Don't show completions if token has changed and the option is set. | |
16 | if (options.closeOnTokenChange && previousToken != null && | |
17 | (tempToken.start != previousToken.start || tempToken.type != previousToken.type)) { | |
18 | return; | |
19 | } | |
20 | ||
21 | var result = getHints(editor, givenOptions); | |
22 | if (!result || !result.list.length) return; | |
23 | var completions = result.list; | |
24 | function insert(str) { | |
25 | editor.replaceRange(str, result.from, result.to); | |
26 | } | |
27 | // When there is only one completion, use it directly. | |
28 | if (options.completeSingle && completions.length == 1) { | |
29 | insert(completions[0]); | |
30 | return true; | |
31 | } | |
32 | ||
33 | // Build the select widget | |
34 | var complete = document.createElement("div"); | |
35 | complete.className = "CodeMirror-completions"; | |
36 | var sel = complete.appendChild(document.createElement("select")); | |
37 | // Opera doesn't move the selection when pressing up/down in a | |
38 | // multi-select, but it does properly support the size property on | |
39 | // single-selects, so no multi-select is necessary. | |
40 | if (!window.opera) sel.multiple = true; | |
41 | for (var i = 0; i < completions.length; ++i) { | |
42 | var opt = sel.appendChild(document.createElement("option")); | |
43 | opt.appendChild(document.createTextNode(completions[i])); | |
44 | } | |
45 | sel.firstChild.selected = true; | |
46 | sel.size = Math.min(10, completions.length); | |
47 | var pos = editor.cursorCoords(options.alignWithWord ? result.from : null); | |
48 | complete.style.left = pos.left + "px"; | |
49 | complete.style.top = pos.bottom + "px"; | |
50 | document.body.appendChild(complete); | |
51 | // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor. | |
52 | var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth); | |
53 | if(winW - pos.left < sel.clientWidth) | |
54 | complete.style.left = (pos.left - sel.clientWidth) + "px"; | |
55 | // Hack to hide the scrollbar. | |
56 | if (completions.length <= 10) | |
57 | complete.style.width = (sel.clientWidth - 1) + "px"; | |
58 | ||
59 | var done = false; | |
60 | function close() { | |
61 | if (done) return; | |
62 | done = true; | |
63 | complete.parentNode.removeChild(complete); | |
64 | } | |
65 | function pick() { | |
66 | insert(completions[sel.selectedIndex]); | |
67 | close(); | |
68 | setTimeout(function(){editor.focus();}, 50); | |
69 | } | |
70 | CodeMirror.on(sel, "blur", close); | |
71 | CodeMirror.on(sel, "keydown", function(event) { | |
72 | var code = event.keyCode; | |
73 | // Enter | |
74 | if (code == 13) {CodeMirror.e_stop(event); pick();} | |
75 | // Escape | |
76 | else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();} | |
77 | else if (code != 38 && code != 40 && code != 33 && code != 34 && !CodeMirror.isModifierKey(event)) { | |
78 | close(); editor.focus(); | |
79 | // Pass the event to the CodeMirror instance so that it can handle things like backspace properly. | |
80 | editor.triggerOnKeyDown(event); | |
81 | // Don't show completions if the code is backspace and the option is set. | |
82 | if (!options.closeOnBackspace || code != 8) { | |
83 | setTimeout(function(){collectHints(tempToken);}, 50); | |
84 | } | |
85 | } | |
86 | }); | |
87 | CodeMirror.on(sel, "dblclick", pick); | |
88 | ||
89 | sel.focus(); | |
90 | // Opera sometimes ignores focusing a freshly created node | |
91 | if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100); | |
92 | return true; | |
93 | } | |
94 | return collectHints(); | |
95 | }; | |
96 | CodeMirror.simpleHint.defaults = { | |
97 | closeOnBackspace: true, | |
98 | closeOnTokenChange: false, | |
99 | completeSingle: true, | |
100 | alignWithWord: true | |
101 | }; | |
102 | })(); |