aboutsummaryrefslogtreecommitdiff
path: root/imports/codemirror/lib/codemirror.js
diff options
context:
space:
mode:
Diffstat (limited to 'imports/codemirror/lib/codemirror.js')
-rw-r--r--[-rwxr-xr-x]imports/codemirror/lib/codemirror.js554
1 files changed, 342 insertions, 212 deletions
diff --git a/imports/codemirror/lib/codemirror.js b/imports/codemirror/lib/codemirror.js
index 79eb457d..9c6e65e4 100755..100644
--- a/imports/codemirror/lib/codemirror.js
+++ b/imports/codemirror/lib/codemirror.js
@@ -1,4 +1,4 @@
1// CodeMirror version 2.2 1// CodeMirror version 2.22
2// 2//
3// All functions that need access to the editor's state live inside 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, 4// the CodeMirror function. Below that, at the bottom of the file,
@@ -6,7 +6,7 @@
6 6
7// CodeMirror is the only global var we claim 7// CodeMirror is the only global var we claim
8var CodeMirror = (function() { 8var CodeMirror = (function() {
9 // This is the function that produces an editor instance. It's 9 // This is the function that produces an editor instance. Its
10 // closure is used to store the editor state. 10 // closure is used to store the editor state.
11 function CodeMirror(place, givenOptions) { 11 function CodeMirror(place, givenOptions) {
12 // Determine effective options based on given values and defaults. 12 // Determine effective options based on given values and defaults.
@@ -22,17 +22,17 @@ var CodeMirror = (function() {
22 // This mess creates the base DOM structure for the editor. 22 // This mess creates the base DOM structure for the editor.
23 wrapper.innerHTML = 23 wrapper.innerHTML =
24 '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea 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" ' + 25 '<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
26 'autocorrect="off" autocapitalize="off"></textarea></div>' + 26 'autocorrect="off" autocapitalize="off"></textarea></div>' +
27 '<div class="CodeMirror-scroll" tabindex="-1">' + 27 '<div class="CodeMirror-scroll" tabindex="-1">' +
28 '<div style="position: relative">' + // Set to the height of the text, causes scrolling 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 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>' + 30 '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
31 // Provides positioning relative to (visible) text origin 31 // Provides positioning relative to (visible) text origin
32 '<div class="CodeMirror-lines"><div style="position: relative">' + 32 '<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
33 '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden"></div>' + 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 34 '<pre class="CodeMirror-cursor">&#160;</pre>' + // Absolutely positioned blinky cursor
35 '<div></div>' + // This DIV contains the actual code 35 '<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
36 '</div></div></div></div></div>'; 36 '</div></div></div></div></div>';
37 if (place.appendChild) place.appendChild(wrapper); else place(wrapper); 37 if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
38 // I've never seen more elegant code in my life. 38 // I've never seen more elegant code in my life.
@@ -40,11 +40,13 @@ var CodeMirror = (function() {
40 scroller = wrapper.lastChild, code = scroller.firstChild, 40 scroller = wrapper.lastChild, code = scroller.firstChild,
41 mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild, 41 mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
42 lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild, 42 lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
43 cursor = measure.nextSibling, lineDiv = cursor.nextSibling; 43 cursor = measure.nextSibling, selectionDiv = cursor.nextSibling,
44 lineDiv = selectionDiv.nextSibling;
44 themeChanged(); 45 themeChanged();
45 // Needed to hide big blue blinking cursor on Mobile Safari 46 // 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 (ios) input.style.width = "0px";
47 if (!webkit) lineSpace.draggable = true; 48 if (!webkit) lineSpace.draggable = true;
49 lineSpace.style.outline = "none";
48 if (options.tabindex != null) input.tabIndex = options.tabindex; 50 if (options.tabindex != null) input.tabIndex = options.tabindex;
49 if (!options.gutter && !options.lineNumbers) gutter.style.display = "none"; 51 if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
50 52
@@ -71,7 +73,8 @@ var CodeMirror = (function() {
71 var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false}; 73 var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
72 // Selection-related flags. shiftSelecting obviously tracks 74 // Selection-related flags. shiftSelecting obviously tracks
73 // whether the user is holding shift. 75 // whether the user is holding shift.
74 var shiftSelecting, lastClick, lastDoubleClick, draggingText, overwrite = false; 76 var shiftSelecting, lastClick, lastDoubleClick, lastScrollPos = 0, draggingText,
77 overwrite = false, suppressEdits = false;
75 // Variables used by startOperation/endOperation to track what 78 // Variables used by startOperation/endOperation to track what
76 // happened during the operation. 79 // happened during the operation.
77 var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone, 80 var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
@@ -83,7 +86,7 @@ var CodeMirror = (function() {
83 var bracketHighlighted; 86 var bracketHighlighted;
84 // Tracks the maximum line length so that the horizontal scrollbar 87 // Tracks the maximum line length so that the horizontal scrollbar
85 // can be kept static when scrolling. 88 // can be kept static when scrolling.
86 var maxLine = "", maxWidth, tabText = computeTabText(); 89 var maxLine = "", maxWidth;
87 90
88 // Initialize the content. 91 // Initialize the content.
89 operation(function(){setValue(options.value || ""); updateInput = false;})(); 92 operation(function(){setValue(options.value || ""); updateInput = false;})();
@@ -99,6 +102,7 @@ var CodeMirror = (function() {
99 // handled in onMouseDown for Gecko. 102 // handled in onMouseDown for Gecko.
100 if (!gecko) connect(scroller, "contextmenu", onContextMenu); 103 if (!gecko) connect(scroller, "contextmenu", onContextMenu);
101 connect(scroller, "scroll", function() { 104 connect(scroller, "scroll", function() {
105 lastScrollPos = scroller.scrollTop;
102 updateDisplay([]); 106 updateDisplay([]);
103 if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px"; 107 if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
104 if (options.onScroll) options.onScroll(instance); 108 if (options.onScroll) options.onScroll(instance);
@@ -116,7 +120,9 @@ var CodeMirror = (function() {
116 connect(scroller, "drop", operation(onDrop)); 120 connect(scroller, "drop", operation(onDrop));
117 connect(scroller, "paste", function(){focusInput(); fastPoll();}); 121 connect(scroller, "paste", function(){focusInput(); fastPoll();});
118 connect(input, "paste", fastPoll); 122 connect(input, "paste", fastPoll);
119 connect(input, "cut", operation(function(){replaceSelection("");})); 123 connect(input, "cut", operation(function(){
124 if (!options.readOnly) replaceSelection("");
125 }));
120 126
121 // IE throws unspecified error in certain cases, when 127 // IE throws unspecified error in certain cases, when
122 // trying to access activeElement before onload 128 // trying to access activeElement before onload
@@ -135,23 +141,30 @@ var CodeMirror = (function() {
135 setValue: operation(setValue), 141 setValue: operation(setValue),
136 getSelection: getSelection, 142 getSelection: getSelection,
137 replaceSelection: operation(replaceSelection), 143 replaceSelection: operation(replaceSelection),
138 focus: function(){focusInput(); onFocus(); fastPoll();}, 144 focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},
139 setOption: function(option, value) { 145 setOption: function(option, value) {
140 var oldVal = options[option]; 146 var oldVal = options[option];
141 options[option] = value; 147 options[option] = value;
142 if (option == "mode" || option == "indentUnit") loadMode(); 148 if (option == "mode" || option == "indentUnit") loadMode();
143 else if (option == "readOnly" && value) {onBlur(); input.blur();} 149 else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();}
150 else if (option == "readOnly" && !value) {resetInput(true);}
144 else if (option == "theme") themeChanged(); 151 else if (option == "theme") themeChanged();
145 else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)(); 152 else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
146 else if (option == "tabSize") operation(tabsChanged)(); 153 else if (option == "tabSize") updateDisplay(true);
147 if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") 154 if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
148 operation(gutterChanged)(); 155 gutterChanged();
156 updateDisplay(true);
157 }
149 }, 158 },
150 getOption: function(option) {return options[option];}, 159 getOption: function(option) {return options[option];},
151 undo: operation(undo), 160 undo: operation(undo),
152 redo: operation(redo), 161 redo: operation(redo),
153 indentLine: operation(function(n, dir) { 162 indentLine: operation(function(n, dir) {
154 if (isLine(n)) indentLine(n, dir == null ? "smart" : dir ? "add" : "subtract"); 163 if (typeof dir != "string") {
164 if (dir == null) dir = options.smartIndent ? "smart" : "prev";
165 else dir = dir ? "add" : "subtract";
166 }
167 if (isLine(n)) indentLine(n, dir);
155 }), 168 }),
156 indentSelection: operation(indentSelected), 169 indentSelection: operation(indentSelected),
157 historySize: function() {return {undo: history.done.length, redo: history.undone.length};}, 170 historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
@@ -248,7 +261,15 @@ var CodeMirror = (function() {
248 moveH: operation(moveH), 261 moveH: operation(moveH),
249 deleteH: operation(deleteH), 262 deleteH: operation(deleteH),
250 moveV: operation(moveV), 263 moveV: operation(moveV),
251 toggleOverwrite: function() {overwrite = !overwrite;}, 264 toggleOverwrite: function() {
265 if(overwrite){
266 overwrite = false;
267 cursor.className = cursor.className.replace(" CodeMirror-overwrite", "");
268 } else {
269 overwrite = true;
270 cursor.className += " CodeMirror-overwrite";
271 }
272 },
252 273
253 posFromIndex: function(off) { 274 posFromIndex: function(off) {
254 var lineNo = 0, ch; 275 var lineNo = 0, ch;
@@ -268,9 +289,18 @@ var CodeMirror = (function() {
268 }); 289 });
269 return index; 290 return index;
270 }, 291 },
292 scrollTo: function(x, y) {
293 if (x != null) scroller.scrollLeft = x;
294 if (y != null) scroller.scrollTop = y;
295 updateDisplay([]);
296 },
271 297
272 operation: function(f){return operation(f)();}, 298 operation: function(f){return operation(f)();},
273 refresh: function(){updateDisplay(true);}, 299 refresh: function(){
300 updateDisplay(true);
301 if (scroller.scrollHeight > lastScrollPos)
302 scroller.scrollTop = lastScrollPos;
303 },
274 getInputField: function(){return input;}, 304 getInputField: function(){return input;},
275 getWrapperElement: function(){return wrapper;}, 305 getWrapperElement: function(){return wrapper;},
276 getScrollerElement: function(){return scroller;}, 306 getScrollerElement: function(){return scroller;},
@@ -297,7 +327,7 @@ var CodeMirror = (function() {
297 } 327 }
298 328
299 function onMouseDown(e) { 329 function onMouseDown(e) {
300 setShift(e.shiftKey); 330 setShift(e_prop(e, "shiftKey"));
301 // Check whether this is a click in a widget 331 // Check whether this is a click in a widget
302 for (var n = e_target(e); n != wrapper; n = n.parentNode) 332 for (var n = e_target(e); n != wrapper; n = n.parentNode)
303 if (n.parentNode == code && n != mover) return; 333 if (n.parentNode == code && n != mover) return;
@@ -339,7 +369,7 @@ var CodeMirror = (function() {
339 } else { lastClick = {time: now, pos: start}; } 369 } else { lastClick = {time: now, pos: start}; }
340 370
341 var last = start, going;