aboutsummaryrefslogtreecommitdiff
path: root/imports/codemirror/lib/codemirror.js
diff options
context:
space:
mode:
Diffstat (limited to 'imports/codemirror/lib/codemirror.js')
-rwxr-xr-ximports/codemirror/lib/codemirror.js2761
1 files changed, 2761 insertions, 0 deletions
diff --git a/imports/codemirror/lib/codemirror.js b/imports/codemirror/lib/codemirror.js
new file mode 100755
index 00000000..79eb457d
--- /dev/null
+++ b/imports/codemirror/lib/codemirror.js
@@ -0,0 +1,2761 @@
1// CodeMirror version 2.2
2//
3// All functions that need access to the editor's state live inside
4// the CodeMirror function. Below that, at the bottom of the file,
5// some utilities are defined.
6
7// CodeMirror is the only global var we claim
8var CodeMirror = (function() {
9 // This is the function that produces an editor instance. It's
10 // closure is used to store the editor state.
11 function CodeMirror(place, givenOptions) {
12 // Determine effective options based on given values and defaults.
13 var options = {}, defaults = CodeMirror.defaults;
14 for (var opt in defaults)
15 if (defaults.hasOwnProperty(opt))
16 options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
17
18 var targetDocument = options["document"];
19 // The element in which the editor lives.
20 var wrapper = targetDocument.createElement("div");
21 wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
22 // This mess creates the base DOM structure for the editor.
23 wrapper.innerHTML =
24 '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
25 '<textarea style="position: absolute; padding: 0; width: 1px;" wrap="off" ' +
26 'autocorrect="off" autocapitalize="off"></textarea></div>' +
27 '<div class="CodeMirror-scroll" tabindex="-1">' +
28 '<div style="position: relative">' + // Set to the height of the text, causes scrolling
29 '<div style="position: relative">' + // Moved around its parent to cover visible view
30 '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
31 // Provides positioning relative to (visible) text origin
32 '<div class="CodeMirror-lines"><div style="position: relative">' +
33 '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden"></div>' +
34 '<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
35 '<div></div>' + // This DIV contains the actual code
36 '</div></div></div></div></div>';
37 if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
38 // I've never seen more elegant code in my life.
39 var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,
40 scroller = wrapper.lastChild, code = scroller.firstChild,
41 mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
42 lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
43 cursor = measure.nextSibling, lineDiv = cursor.nextSibling;
44 themeChanged();
45 // Needed to hide big blue blinking cursor on Mobile Safari
46 if (/AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent)) input.style.width = "0px";
47 if (!webkit) lineSpace.draggable = true;
48 if (options.tabindex != null) input.tabIndex = options.tabindex;
49 if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
50
51 // Check for problem with IE innerHTML not working when we have a
52 // P (or similar) parent node.
53 try { stringWidth("x"); }
54 catch (e) {
55 if (e.message.match(/runtime/i))
56 e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)");
57 throw e;
58 }
59
60 // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.
61 var poll = new Delayed(), highlight = new Delayed(), blinker;
62
63 // mode holds a mode API object. doc is the tree of Line objects,
64 // work an array of lines that should be parsed, and history the
65 // undo history (instance of History constructor).
66 var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), work, focused;
67 loadMode();
68 // The selection. These are always maintained to point at valid
69 // positions. Inverted is used to remember that the user is
70 // selecting bottom-to-top.
71 var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
72 // Selection-related flags. shiftSelecting obviously tracks
73 // whether the user is holding shift.
74 var shiftSelecting, lastClick, lastDoubleClick, draggingText, overwrite = false;
75 // Variables used by startOperation/endOperation to track what
76 // happened during the operation.
77 var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
78 gutterDirty, callbacks;
79 // Current visible range (may be bigger than the view window).
80 var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
81 // bracketHighlighted is used to remember that a backet has been
82 // marked.
83 var bracketHighlighted;
84 // Tracks the maximum line length so that the horizontal scrollbar
85 // can be kept static when scrolling.
86 var maxLine = "", maxWidth, tabText = computeTabText();
87
88 // Initialize the content.
89 operation(function(){setValue(options.value || ""); updateInput = false;})();
90 var history = new History();
91
92 // Register our event handlers.
93 connect(scroller, "mousedown", operation(onMouseDown));
94 connect(scroller, "dblclick", operation(onDoubleClick));
95 connect(lineSpace, "dragstart", onDragStart);
96 connect(lineSpace, "selectstart", e_preventDefault);
97 // Gecko browsers fire contextmenu *after* opening the menu, at
98 // which point we can't mess with it anymore. Context menu is
99 // handled in onMouseDown for Gecko.
100 if (!gecko) connect(scroller, "contextmenu", onContextMenu);
101 connect(scroller, "scroll", function() {
102 updateDisplay([]);
103 if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
104 if (options.onScroll) options.onScroll(instance);
105 });
106 connect(window, "resize", function() {updateDisplay(true);});
107 connect(input, "keyup", operation(onKeyUp));
108 connect(input, "input", fastPoll);
109 connect(input, "keydown", operation(onKeyDown));
110 connect(input, "keypress", operation(onKeyPress));
111 connect(input, "focus", onFocus);
112 connect(input, "blur", onBlur);
113
114 connect(scroller, "dragenter", e_stop);
115 connect(scroller, "dragover", e_stop);
116 connect(scroller, "drop", operation(onDrop));
117 connect(scroller, "paste", function(){focusInput(); fastPoll();});
118 connect(input, "paste", fastPoll);
119 connect(input, "cut", operation(function(){replaceSelection("");}));
120
121 // IE throws unspecified error in certain cases, when
122 // trying to access activeElement before onload
123 var hasFocus; try { hasFocus = (targetDocument.activeElement == input); } catch(e) { }
124 if (hasFocus) setTimeout(onFocus, 20);
125 else onBlur();
126
127 function isLine(l) {return l >= 0 && l < doc.size;}
128 // The instance object that we'll return. Mostly calls out to
129 // local functions in the CodeMirror function. Some do some extra
130 // range checking and/or clipping. operation is used to wrap the
131 // call so that changes it makes are tracked, and the display is
132 // updated afterwards.
133 var instance = wrapper.CodeMirror = {
134 getValue: getValue,
135 setValue: operation(setValue),
136 getSelection: getSelection,
137 replaceSelection: operation(replaceSelection),
138 focus: function(){focusInput(); onFocus(); fastPoll();},
139 setOption: function(option, value) {
140 var oldVal = options[option];
141 options[option] = value;
142 if (option == "mode" || option == "indentUnit") loadMode();
143 else if (option == "readOnly" && value) {onBlur(); input.blur();}
144 else if (option == "theme") themeChanged();
145 else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
146 else if (option == "tabSize") operation(tabsChanged)();
147 if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme")
148 operation(gutterChanged)();
149 },
150 getOption: function(option) {return options[option];},
151 undo: operation(undo),
152 redo: operation(redo),
153 indentLine: operation(function(n, dir) {
154 if (isLine(n)) indentLine(n, dir == null ? "smart" : dir ? "add" : "subtract");
155 }),
156 indentSelection: operation(indentSelected),
157 historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
158 clearHistory: function() {history = new History();},
159 matchBrackets: operation(function(){matchBrackets(true);}),
160 getTokenAt: operation(function(pos) {
161 pos = clipPos(pos);
162 return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);
163 }),
164 getStateAfter: function(line) {
165 line = clipLine(line == null ? doc.size - 1: line);
166 return getStateBefore(line + 1);
167 },
168 cursorCoords: function(start){
169 if (start == null) start = sel.inverted;
170 return pageCoords(start ? sel.from : sel.to);
171 },
172 charCoords: function(pos){return pageCoords(clipPos(pos));},
173 coordsChar: function(coords) {
174 var off = eltOffset(lineSpace);
175 return coordsChar(coords.x - off.left, coords.y - off.top);
176 },
177 markText: operation(markText),
178 setBookmark: setBookmark,
179 setMarker: operation(addGutterMarker),
180 clearMarker: operation(removeGutterMarker),
181 setLineClass: operation(setLineClass),
182 hideLine: operation(function(h) {return setLineHidden(h, true);}),
183 showLine: operation(function(h) {return setLineHidden(h, false);}),
184 onDeleteLine: function(line, f) {
185 if (typeof line == "number") {
186 if (!isLine(line)) return null;
187 line = getLine(line);
188 }
189 (line.handlers || (line.handlers = [])).push(f);
190 return line;
191 },
192 lineInfo: lineInfo,
193 addWidget: function(pos, node, scroll, vert, horiz) {
194 pos = localCoords(clipPos(pos));
195 var top = pos.yBot, left = pos.x;
196 node.style.position = "absolute";
197 code.appendChild(node);
198 if (vert == "over") top = pos.y;
199 else if (vert == "near") {
200 var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),
201 hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();
202 if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
203 top = pos.y - node.offsetHeight;
204 if (left + node.offsetWidth > hspace)
205 left = hspace - node.offsetWidth;
206 }
207 node.style.top = (top + paddingTop()) + "px";
208 node.style.left = node.style.right = "";
209 if (horiz == "right") {
210 left = code.clientWidth - node.offsetWidth;
211 node.style.right = "0px";
212 } else {
213 if (horiz == "left") left = 0;
214 else if (horiz == "middle") left = (code.clientWidth - node.offsetWidth) / 2;
215 node.style.left = (left + paddingLeft()) + "px";
216 }
217 if (scroll)
218 scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);
219 },
220
221 lineCount: function() {return doc.size;},