123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- (function() {
- CodeMirror.simpleHint = function(editor, getHints, givenOptions) {
- // Determine effective options based on given values and defaults.
- var options = {}, defaults = CodeMirror.simpleHint.defaults;
- for (var opt in defaults)
- if (defaults.hasOwnProperty(opt))
- options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
-
- function collectHints(previousToken) {
- // We want a single cursor position.
- if (editor.somethingSelected()) return;
- var tempToken = editor.getTokenAt(editor.getCursor());
- // Don't show completions if token has changed and the option is set.
- if (options.closeOnTokenChange && previousToken != null &&
- (tempToken.start != previousToken.start || tempToken.type != previousToken.type)) {
- return;
- }
- var result = getHints(editor, givenOptions);
- if (!result || !result.list.length) return;
- var completions = result.list;
- function insert(str) {
- editor.replaceRange(str, result.from, result.to);
- }
- // When there is only one completion, use it directly.
- if (options.completeSingle && completions.length == 1) {
- insert(completions[0]);
- return true;
- }
- // Build the select widget
- var complete = document.createElement("div");
- complete.className = "CodeMirror-completions";
- var sel = complete.appendChild(document.createElement("select"));
- // Opera doesn't move the selection when pressing up/down in a
- // multi-select, but it does properly support the size property on
- // single-selects, so no multi-select is necessary.
- if (!window.opera) sel.multiple = true;
- for (var i = 0; i < completions.length; ++i) {
- var opt = sel.appendChild(document.createElement("option"));
- opt.appendChild(document.createTextNode(completions[i]));
- }
- sel.firstChild.selected = true;
- sel.size = Math.min(10, completions.length);
- var pos = editor.cursorCoords(options.alignWithWord ? result.from : null);
- complete.style.left = pos.left + "px";
- complete.style.top = pos.bottom + "px";
- document.body.appendChild(complete);
- // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
- var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
- if(winW - pos.left < sel.clientWidth)
- complete.style.left = (pos.left - sel.clientWidth) + "px";
- // Hack to hide the scrollbar.
- if (completions.length <= 10)
- complete.style.width = (sel.clientWidth - 1) + "px";
- var done = false;
- function close() {
- if (done) return;
- done = true;
- complete.parentNode.removeChild(complete);
- }
- function pick() {
- insert(completions[sel.selectedIndex]);
- close();
- setTimeout(function(){editor.focus();}, 50);
- }
- CodeMirror.on(sel, "blur", close);
- CodeMirror.on(sel, "keydown", function(event) {
- var code = event.keyCode;
- // Enter
- if (code == 13) {CodeMirror.e_stop(event); pick();}
- // Escape
- else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
- else if (code != 38 && code != 40 && code != 33 && code != 34 && !CodeMirror.isModifierKey(event)) {
- close(); editor.focus();
- // Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
- editor.triggerOnKeyDown(event);
- // Don't show completions if the code is backspace and the option is set.
- if (!options.closeOnBackspace || code != 8) {
- setTimeout(function(){collectHints(tempToken);}, 50);
- }
- }
- });
- CodeMirror.on(sel, "dblclick", pick);
- sel.focus();
- // Opera sometimes ignores focusing a freshly created node
- if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);
- return true;
- }
- return collectHints();
- };
- CodeMirror.simpleHint.defaults = {
- closeOnBackspace: true,
- closeOnTokenChange: false,
- completeSingle: true,
- alignWithWord: true
- };
- })();
|