PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.3
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.3
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
profile-builder / assets / lib / codemirror / addon / hint / show-hint.js

show-hint.js in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 4.0.3, at assets/lib/codemirror/addon/hint/show-hint.js

275 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function() {
2 "use strict";
3
4 CodeMirror.showHint = function(cm, getHints, options) {
5 // We want a single cursor position.
6 if (cm.somethingSelected()) return;
7 if (getHints == null) getHints = cm.getHelper(cm.getCursor(), "hint");
8 if (getHints == null) return;
9
10 if (cm.state.completionActive) cm.state.completionActive.close();
11
12 var completion = cm.state.completionActive = new Completion(cm, getHints, options || {});
13 CodeMirror.signal(cm, "startCompletion", cm);
14 if (completion.options.async)
15 getHints(cm, function(hints) { completion.showHints(hints); }, completion.options);
16 else
17 return completion.showHints(getHints(cm, completion.options));
18 };
19
20 function Completion(cm, getHints, options) {
21 this.cm = cm;
22 this.getHints = getHints;
23 this.options = options;
24 this.widget = this.onClose = null;
25 }
26
27 Completion.prototype = {
28 close: function() {
29 if (!this.active()) return;
30 this.cm.state.completionActive = null;
31
32 if (this.widget) this.widget.close();
33 if (this.onClose) this.onClose();
34 CodeMirror.signal(this.cm, "endCompletion", this.cm);
35 },
36
37 active: function() {
38 return this.cm.state.completionActive == this;
39 },
40
41 pick: function(data, i) {
42 var completion = data.list[i];
43 if (completion.hint) completion.hint(this.cm, data, completion);
44 else this.cm.replaceRange(getText(completion), data.from, data.to);
45 this.close();
46 },
47
48 showHints: function(data) {
49 if (!data || !data.list.length || !this.active()) return this.close();
50
51 if (this.options.completeSingle != false && data.list.length == 1)
52 this.pick(data, 0);
53 else
54 this.showWidget(data);
55 },
56
57 showWidget: function(data) {
58 this.widget = new Widget(this, data);
59 CodeMirror.signal(data, "shown");
60
61 var debounce = null, completion = this, finished;
62 var closeOn = this.options.closeCharacters || /[\s()\[\]{};:>,]/;
63 var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
64
65 function done() {
66 if (finished) return;
67 finished = true;
68 completion.close();
69 completion.cm.off("cursorActivity", activity);
70 if (data) CodeMirror.signal(data, "close");
71 }
72
73 function update() {
74 if (finished) return;
75 CodeMirror.signal(data, "update");
76 if (completion.options.async)
77 completion.getHints(completion.cm, finishUpdate, completion.options);
78 else
79 finishUpdate(completion.getHints(completion.cm, completion.options));
80 }
81 function finishUpdate(data_) {
82 data = data_;
83 if (finished) return;
84 if (!data || !data.list.length) return done();
85 completion.widget = new Widget(completion, data);
86 }
87
88 function activity() {
89 clearTimeout(debounce);
90 var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
91 if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
92 pos.ch < startPos.ch || completion.cm.somethingSelected() ||
93 (pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
94 completion.close();
95 } else {
96 debounce = setTimeout(update, 170);
97 if (completion.widget) completion.widget.close();
98 }
99 }
100 this.cm.on("cursorActivity", activity);
101 this.onClose = done;
102 }
103 };
104
105 function getText(completion) {
106 if (typeof completion == "string") return completion;
107 else return completion.text;
108 }
109
110 function buildKeyMap(options, handle) {
111 var baseMap = {
112 Up: function() {handle.moveFocus(-1);},
113 Down: function() {handle.moveFocus(1);},
114 PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
115 PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
116 Home: function() {handle.setFocus(0);},
117 End: function() {handle.setFocus(handle.length - 1);},
118 Enter: handle.pick,
119 Tab: handle.pick,
120 Esc: handle.close
121 };
122 var ourMap = options.customKeys ? {} : baseMap;
123 function addBinding(key, val) {
124 var bound;
125 if (typeof val != "string")
126 bound = function(cm) { return val(cm, handle); };
127 // This mechanism is deprecated
128 else if (baseMap.hasOwnProperty(val))
129 bound = baseMap[val];
130 else
131 bound = val;
132 ourMap[key] = bound;
133 }
134 if (options.customKeys)
135 for (var key in options.customKeys) if (options.customKeys.hasOwnProperty(key))
136 addBinding(key, options.customKeys[key]);
137 if (options.extraKeys)
138 for (var key in options.extraKeys) if (options.extraKeys.hasOwnProperty(key))
139 addBinding(key, options.extraKeys[key]);
140 return ourMap;
141 }
142
143 function Widget(completion, data) {
144 this.completion = completion;
145 this.data = data;
146 var widget = this, cm = completion.cm, options = completion.options;
147
148 var hints = this.hints = document.createElement("ul");
149 hints.className = "CodeMirror-hints";
150 this.selectedHint = 0;
151
152 var completions = data.list;
153 for (var i = 0; i < completions.length; ++i) {
154 var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
155 var className = "CodeMirror-hint" + (i ? "" : " CodeMirror-hint-active");
156 if (cur.className != null) className = cur.className + " " + className;
157 elt.className = className;
158 if (cur.render) cur.render(elt, data, cur);
159 else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
160 elt.hintId = i;
161 }
162
163 var pos = cm.cursorCoords(options.alignWithWord !== false ? data.from : null);
164 var left = pos.left, top = pos.bottom, below = true;
165 hints.style.left = left + "px";
166 hints.style.top = top + "px";
167 // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
168 var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
169 var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
170 (options.container || document.body).appendChild(hints);
171 var box = hints.getBoundingClientRect();
172 var overlapX = box.right - winW, overlapY = box.bottom - winH;
173 if (overlapX > 0) {
174 if (box.right - box.left > winW) {
175 hints.style.width = (winW - 5) + "px";
176 overlapX -= (box.right - box.left) - winW;
177 }
178 hints.style.left = (left = pos.left - overlapX) + "px";
179 }
180 if (overlapY > 0) {
181 var height = box.bottom - box.top;
182 if (box.top - (pos.bottom - pos.top) - height > 0) {
183 overlapY = height + (pos.bottom - pos.top);
184 below = false;
185 } else if (height > winH) {
186 hints.style.height = (winH - 5) + "px";
187 overlapY -= height - winH;
188 }
189 hints.style.top = (top = pos.bottom - overlapY) + "px";
190 }
191
192 cm.addKeyMap(this.keyMap = buildKeyMap(options, {
193 moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
194 setFocus: function(n) { widget.changeActive(n); },
195 menuSize: function() { return widget.screenAmount(); },
196 length: completions.length,
197 close: function() { completion.close(); },
198 pick: function() { widget.pick(); }
199 }));
200
201 if (options.closeOnUnfocus !== false) {
202 var closingOnBlur;
203 cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
204 cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
205 }
206
207 var startScroll = cm.getScrollInfo();
208 cm.on("scroll", this.onScroll = function() {
209 var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
210 var newTop = top + startScroll.top - curScroll.top;
211 var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
212 if (!below) point += hints.offsetHeight;
213 if (point <= editor.top || point >= editor.bottom) return completion.close();
214 hints.style.top = newTop + "px";
215 hints.style.left = (left + startScroll.left - curScroll.left) + "px";
216 });
217
218 CodeMirror.on(hints, "dblclick", function(e) {
219 var t = e.target || e.srcElement;
220 if (t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
221 });
222 CodeMirror.on(hints, "click", function(e) {
223 var t = e.target || e.srcElement;
224 if (t.hintId != null) widget.changeActive(t.hintId);
225 });
226 CodeMirror.on(hints, "mousedown", function() {
227 setTimeout(function(){cm.focus();}, 20);
228 });
229
230 CodeMirror.signal(data, "select", completions[0], hints.firstChild);
231 return true;
232 }
233
234 Widget.prototype = {
235 close: function() {
236 if (this.completion.widget != this) return;
237 this.completion.widget = null;
238 this.hints.parentNode.removeChild(this.hints);
239 this.completion.cm.removeKeyMap(this.keyMap);
240
241 var cm = this.completion.cm;
242 if (this.completion.options.closeOnUnfocus !== false) {
243 cm.off("blur", this.onBlur);
244 cm.off("focus", this.onFocus);
245 }
246 cm.off("scroll", this.onScroll);
247 },
248
249 pick: function() {
250 this.completion.pick(this.data, this.selectedHint);
251 },
252
253 changeActive: function(i, avoidWrap) {
254 if (i >= this.data.list.length)
255 i = avoidWrap ? this.data.list.length - 1 : 0;
256 else if (i < 0)
257 i = avoidWrap ? 0 : this.data.list.length - 1;
258 if (this.selectedHint == i) return;
259 var node = this.hints.childNodes[this.selectedHint];
260 node.className = node.className.replace(" CodeMirror-hint-active", "");
261 node = this.hints.childNodes[this.selectedHint = i];
262 node.className += " CodeMirror-hint-active";
263 if (node.offsetTop < this.hints.scrollTop)
264 this.hints.scrollTop = node.offsetTop - 3;
265 else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
266 this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
267 CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
268 },
269
270 screenAmount: function() {
271 return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
272 }
273 };
274 })();
275