diff options
Diffstat (limited to 'imports/codemirror/lib/codemirror.js')
-rw-r--r-- | imports/codemirror/lib/codemirror.js | 619 |
1 files changed, 414 insertions, 205 deletions
diff --git a/imports/codemirror/lib/codemirror.js b/imports/codemirror/lib/codemirror.js index 5434a8dd..250d5b18 100644 --- a/imports/codemirror/lib/codemirror.js +++ b/imports/codemirror/lib/codemirror.js | |||
@@ -1,4 +1,4 @@ | |||
1 | // CodeMirror version 2.23 | 1 | // CodeMirror version 2.3 |
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, |
@@ -23,14 +23,19 @@ var CodeMirror = (function() { | |||
23 | '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea | 23 | '<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea |
24 | '<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' + | 24 | '<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' + |
25 | 'autocorrect="off" autocapitalize="off"></textarea></div>' + | 25 | 'autocorrect="off" autocapitalize="off"></textarea></div>' + |
26 | '<div class="CodeMirror-scrollbar">' + // The vertical scrollbar. Horizontal scrolling is handled by the scroller itself. | ||
27 | '<div class="CodeMirror-scrollbar-inner">' + // The empty scrollbar content, used solely for managing the scrollbar thumb. | ||
28 | '</div></div>' + // This must be before the scroll area because it's float-right. | ||
26 | '<div class="CodeMirror-scroll" tabindex="-1">' + | 29 | '<div class="CodeMirror-scroll" tabindex="-1">' + |
27 | '<div style="position: relative">' + // Set to the height of the text, causes scrolling | 30 | '<div style="position: relative">' + // Set to the height of the text, causes scrolling |
28 | '<div style="position: relative">' + // Moved around its parent to cover visible view | 31 | '<div style="position: relative">' + // Moved around its parent to cover visible view |
29 | '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' + | 32 | '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' + |
30 | // Provides positioning relative to (visible) text origin | 33 | // Provides positioning relative to (visible) text origin |
31 | '<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' + | 34 | '<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' + |
35 | // Used to measure text size | ||
32 | '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden;"></div>' + | 36 | '<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden;"></div>' + |
33 | '<pre class="CodeMirror-cursor"> </pre>' + // Absolutely positioned blinky cursor | 37 | '<pre class="CodeMirror-cursor"> </pre>' + // Absolutely positioned blinky cursor |
38 | '<pre class="CodeMirror-cursor" style="visibility: hidden"> </pre>' + // Used to force a width | ||
34 | '<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code | 39 | '<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code |
35 | '</div></div></div></div></div>'; | 40 | '</div></div></div></div></div>'; |
36 | if (place.appendChild) place.appendChild(wrapper); else place(wrapper); | 41 | if (place.appendChild) place.appendChild(wrapper); else place(wrapper); |
@@ -39,12 +44,13 @@ var CodeMirror = (function() { | |||
39 | scroller = wrapper.lastChild, code = scroller.firstChild, | 44 | scroller = wrapper.lastChild, code = scroller.firstChild, |
40 | mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild, | 45 | mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild, |
41 | lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild, | 46 | lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild, |
42 | cursor = measure.nextSibling, selectionDiv = cursor.nextSibling, | 47 | cursor = measure.nextSibling, widthForcer = cursor.nextSibling, |
43 | lineDiv = selectionDiv.nextSibling; | 48 | selectionDiv = widthForcer.nextSibling, lineDiv = selectionDiv.nextSibling, |
44 | themeChanged(); | 49 | scrollbar = inputDiv.nextSibling, scrollbarInner = scrollbar.firstChild; |
50 | themeChanged(); keyMapChanged(); | ||
45 | // Needed to hide big blue blinking cursor on Mobile Safari | 51 | // Needed to hide big blue blinking cursor on Mobile Safari |
46 | if (ios) input.style.width = "0px"; | 52 | if (ios) input.style.width = "0px"; |
47 | if (!webkit) lineSpace.draggable = true; | 53 | if (!webkit) scroller.draggable = true; |
48 | lineSpace.style.outline = "none"; | 54 | lineSpace.style.outline = "none"; |
49 | if (options.tabindex != null) input.tabIndex = options.tabindex; | 55 | if (options.tabindex != null) input.tabIndex = options.tabindex; |
50 | if (options.autofocus) focusInput(); | 56 | if (options.autofocus) focusInput(); |
@@ -52,6 +58,17 @@ var CodeMirror = (function() { | |||
52 | // Needed to handle Tab key in KHTML | 58 | // Needed to handle Tab key in KHTML |
53 | if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute"; | 59 | if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute"; |
54 | 60 | ||
61 | // Check for OS X >= 10.7. If so, we need to force a width on the scrollbar, and | ||
62 | // make it overlap the content. (But we only do this if the scrollbar doesn't already | ||
63 | // have a natural width. If the mouse is plugged in or the user sets the system pref | ||
64 | // to always show scrollbars, the scrollbar shouldn't overlap.) | ||
65 | if (mac_geLion) { | ||
66 | scrollbar.className += (overlapScrollbars() ? " cm-sb-overlap" : " cm-sb-nonoverlap"); | ||
67 | } else if (ie_lt8) { | ||
68 | // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). | ||
69 | scrollbar.className += " cm-sb-ie7"; | ||
70 | } | ||
71 | |||
55 | // Check for problem with IE innerHTML not working when we have a | 72 | // Check for problem with IE innerHTML not working when we have a |
56 | // P (or similar) parent node. | 73 | // P (or similar) parent node. |
57 | try { stringWidth("x"); } | 74 | try { stringWidth("x"); } |
@@ -75,7 +92,7 @@ var CodeMirror = (function() { | |||
75 | var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false}; | 92 | var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false}; |
76 | // Selection-related flags. shiftSelecting obviously tracks | 93 | // Selection-related flags. shiftSelecting obviously tracks |
77 | // whether the user is holding shift. | 94 | // whether the user is holding shift. |
78 | var shiftSelecting, lastClick, lastDoubleClick, lastScrollPos = 0, draggingText, | 95 | var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, lastScrollLeft = 0, draggingText, |
79 | overwrite = false, suppressEdits = false; | 96 | overwrite = false, suppressEdits = false; |
80 | // Variables used by startOperation/endOperation to track what | 97 | // Variables used by startOperation/endOperation to track what |
81 | // happened during the operation. | 98 | // happened during the operation. |
@@ -88,7 +105,7 @@ var CodeMirror = (function() { | |||
88 | var bracketHighlighted; | 105 | var bracketHighlighted; |
89 | // Tracks the maximum line length so that the horizontal scrollbar | 106 | // Tracks the maximum line length so that the horizontal scrollbar |
90 | // can be kept static when scrolling. | 107 | // can be kept static when scrolling. |
91 | var maxLine = "", maxWidth; | 108 | var maxLine = "", updateMaxLine = false, maxLineChanged = true; |
92 | var tabCache = {}; | 109 | var tabCache = {}; |
93 | 110 | ||
94 | // Initialize the content. | 111 | // Initialize the content. |
@@ -98,18 +115,16 @@ var CodeMirror = (function() { | |||
98 | // Register our event handlers. | 115 | // Register our event handlers. |
99 | connect(scroller, "mousedown", operation(onMouseDown)); | 116 | connect(scroller, "mousedown", operation(onMouseDown)); |
100 | connect(scroller, "dblclick", operation(onDoubleClick)); | 117 | connect(scroller, "dblclick", operation(onDoubleClick)); |
101 | connect(lineSpace, "dragstart", onDragStart); | ||
102 | connect(lineSpace, "selectstart", e_preventDefault); | 118 | connect(lineSpace, "selectstart", e_preventDefault); |
103 | // Gecko browsers fire contextmenu *after* opening the menu, at | 119 | // Gecko browsers fire contextmenu *after* opening the menu, at |
104 | // which point we can't mess with it anymore. Context menu is | 120 | // which point we can't mess with it anymore. Context menu is |
105 | // handled in onMouseDown for Gecko. | 121 | // handled in onMouseDown for Gecko. |
106 | if (!gecko) connect(scroller, "contextmenu", onContextMenu); | 122 | if (!gecko) connect(scroller, "contextmenu", onContextMenu); |
107 | connect(scroller, "scroll", function() { | 123 | connect(scroller, "scroll", onScroll); |
108 | lastScrollPos = scroller.scrollTop; | 124 | connect(scrollbar, "scroll", onScroll); |
109 | updateDisplay([]); | 125 | connect(scrollbar, "mousedown", function() {setTimeout(focusInput, 0);}); |
110 | if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px"; | 126 | connect(scroller, "mousewheel", onMouseWheel); |
111 | if (options.onScroll) options.onScroll(instance); | 127 | connect(scroller, "DOMMouseScroll", onMouseWheel); |
112 | }); | ||
113 | connect(window, "resize", function() {updateDisplay(true);}); | 128 | connect(window, "resize", function() {updateDisplay(true);}); |
114 | connect(input, "keyup", operation(onKeyUp)); | 129 | connect(input, "keyup", operation(onKeyUp)); |
115 | connect(input, "input", fastPoll); | 130 | connect(input, "input", fastPoll); |
@@ -118,9 +133,16 @@ var CodeMirror = (function() { | |||
118 | connect(input, "focus", onFocus); | 133 | connect(input, "focus", onFocus); |
119 | connect(input, "blur", onBlur); | 134 | connect(input, "blur", onBlur); |
120 | 135 | ||
121 | connect(scroller, "dragenter", e_stop); | 136 | if (options.dragDrop) { |
122 | connect(scroller, "dragover", e_stop); | 137 | connect(scroller, "dragstart", onDragStart); |
123 | connect(scroller, "drop", operation(onDrop)); | 138 | function drag_(e) { |
139 | if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return; | ||
140 | e_stop(e); | ||
141 | } | ||
142 | connect(scroller, "dragenter", drag_); | ||
143 | connect(scroller, "dragover", drag_); | ||
144 | connect(scroller, "drop", operation(onDrop)); | ||
145 | } | ||
124 | connect(scroller, "paste", function(){focusInput(); fastPoll();}); | 146 | connect(scroller, "paste", function(){focusInput(); fastPoll();}); |
125 | connect(input, "paste", fastPoll); | 147 | connect(input, "paste", fastPoll); |
126 | connect(input, "cut", operation(function(){ | 148 | connect(input, "cut", operation(function(){ |
@@ -160,6 +182,7 @@ var CodeMirror = (function() { | |||
160 | else if (option == "theme") themeChanged(); | 182 | else if (option == "theme") themeChanged(); |
161 | else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)(); | 183 | else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)(); |
162 | else if (option == "tabSize") updateDisplay(true); | 184 | else if (option == "tabSize") updateDisplay(true); |
185 | else if (option == "keyMap") keyMapChanged(); | ||
163 | if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") { | 186 | if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") { |
164 | gutterChanged(); | 187 | gutterChanged(); |
165 | updateDisplay(true); | 188 | updateDisplay(true); |
@@ -307,15 +330,20 @@ var CodeMirror = (function() { | |||
307 | }, | 330 | }, |
308 | scrollTo: function(x, y) { | 331 | scrollTo: function(x, y) { |
309 | if (x != null) scroller.scrollLeft = x; | 332 | if (x != null) scroller.scrollLeft = x; |
310 | if (y != null) scroller.scrollTop = y; | 333 | if (y != null) scrollbar.scrollTop = y; |
311 | updateDisplay([]); | 334 | updateDisplay([]); |
312 | }, | 335 | }, |
336 | getScrollInfo: function() { | ||
337 | return {x: scroller.scrollLeft, y: scrollbar.scrollTop, | ||
338 | height: scrollbar.scrollHeight, width: scroller.scrollWidth}; | ||
339 | }, | ||
313 | 340 | ||
314 | operation: function(f){return operation(f)();}, | 341 | operation: function(f){return operation(f)();}, |
342 | compoundChange: function(f){return compoundChange(f);}, | ||
315 | refresh: function(){ | 343 | refresh: function(){ |
316 | updateDisplay(true); | 344 | updateDisplay(true); |
317 | if (scroller.scrollHeight > lastScrollPos) | 345 | if (scrollbar.scrollHeight > lastScrollTop) |
318 | scroller.scrollTop = lastScrollPos; | 346 | scrollbar.scrollTop = lastScrollTop; |
319 | }, | 347 | }, |
320 | getInputField: function(){return input;}, | 348 | getInputField: function(){return input;}, |
321 | getWrapperElement: function(){return wrapper;}, | 349 | getWrapperElement: function(){return wrapper;}, |
@@ -336,12 +364,22 @@ var CodeMirror = (function() { | |||
336 | splitLines(code), top, top); | 364 | splitLines(code), top, top); |
337 | updateInput = true; | 365 | updateInput = true; |
338 | } | 366 | } |
339 | function getValue(code) { | 367 | function getValue() { |
340 | var text = []; | 368 | var text = []; |
341 | doc.iter(0, doc.size, function(line) { text.push(line.text); }); | 369 | doc.iter(0, doc.size, function(line) { text.push(line.text); }); |
342 | return text.join("\n"); | 370 | return text.join("\n"); |
343 | } | 371 | } |
344 | 372 | ||
373 | function onScroll(e) { | ||
374 | if (lastScrollTop != scrollbar.scrollTop || lastScrollLeft != scroller.scrollLeft) { | ||
375 | lastScrollTop = scrollbar.scrollTop; | ||
376 | lastScrollLeft = scroller.scrollLeft; | ||
377 | updateDisplay([]); | ||
378 | if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px"; | ||
379 | if (options.onScroll) options.onScroll(instance); | ||
380 | } | ||
381 | } | ||
382 | |||
345 | function onMouseDown(e) { | 383 | function onMouseDown(e) { |
346 | setShift(e_prop(e, "shiftKey")); | 384 | setShift(e_prop(e, "shiftKey")); |