summaryrefslogtreecommitdiff
path: root/codemirror_ui/lib/CodeMirror-2.3/lib/util/simple-hint.js
blob: 7decd5875ed9d28675d34276f4cb6870fb10e310 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
(function() {
  CodeMirror.simpleHint = function(editor, getHints) {
    // We want a single cursor position.
    if (editor.somethingSelected()) return;
    var result = getHints(editor);
    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 (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();
    complete.style.left = pos.x + "px";
    complete.style.top = pos.yBot + "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.x < sel.clientWidth)
      complete.style.left = (pos.x - 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.connect(sel, "blur", close);
    CodeMirror.connect(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) {
        close(); editor.focus();
        // Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
        editor.triggerOnKeyDown(event);
        setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
      }
    });
    CodeMirror.connect(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;
  };
})();