diff options
Diffstat (limited to 'imports/codemirror/lib/codemirror.js')
-rwxr-xr-x | imports/codemirror/lib/codemirror.js | 2761 |
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 | ||
8 | var 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"> </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 | }, | ||