codemirror-rails 2.2.1 → 2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +8 -0
- data/codemirror-rails.gemspec +1 -1
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +842 -422
- data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +2 -2
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +722 -32
- data/vendor/assets/javascripts/codemirror/modes/clike.js +31 -9
- data/vendor/assets/javascripts/codemirror/modes/clojure.js +14 -14
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +59 -37
- data/vendor/assets/javascripts/codemirror/modes/css.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/diff.js +24 -5
- data/vendor/assets/javascripts/codemirror/modes/ecl.js +203 -0
- data/vendor/assets/javascripts/codemirror/modes/erlang.js +251 -0
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +40 -4
- data/vendor/assets/javascripts/codemirror/modes/go.js +170 -0
- data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +4 -2
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +10 -9
- data/vendor/assets/javascripts/codemirror/modes/less.js +232 -0
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +52 -49
- data/vendor/assets/javascripts/codemirror/modes/mysql.js +188 -0
- data/vendor/assets/javascripts/codemirror/modes/pascal.js +2 -46
- data/vendor/assets/javascripts/codemirror/modes/perl.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/php.js +55 -25
- data/vendor/assets/javascripts/codemirror/modes/pig.js +172 -0
- data/vendor/assets/javascripts/codemirror/modes/properties.js +63 -0
- data/vendor/assets/javascripts/codemirror/modes/python.js +37 -32
- data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/rst.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/ruby.js +14 -14
- data/vendor/assets/javascripts/codemirror/modes/rust.js +36 -15
- data/vendor/assets/javascripts/codemirror/modes/scheme.js +74 -46
- data/vendor/assets/javascripts/codemirror/modes/shell.js +103 -0
- data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +16 -16
- data/vendor/assets/javascripts/codemirror/modes/smarty.js +148 -0
- data/vendor/assets/javascripts/codemirror/modes/stex.js +21 -6
- data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +55 -45
- data/vendor/assets/javascripts/codemirror/modes/tiki.js +316 -0
- data/vendor/assets/javascripts/codemirror/modes/vbscript.js +26 -0
- data/vendor/assets/javascripts/codemirror/modes/verilog.js +194 -0
- data/vendor/assets/javascripts/codemirror/modes/xml.js +89 -16
- data/vendor/assets/javascripts/codemirror/modes/xmlpure.js +5 -0
- data/vendor/assets/javascripts/codemirror/modes/xquery.js +448 -0
- data/vendor/assets/javascripts/codemirror/utils/closetag.js +146 -0
- data/vendor/assets/javascripts/codemirror/utils/dialog.js +63 -0
- data/vendor/assets/javascripts/codemirror/utils/foldcode.js +196 -0
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +297 -0
- data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +134 -0
- data/vendor/assets/javascripts/codemirror/utils/loadmode.js +51 -0
- data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +44 -0
- data/vendor/assets/javascripts/codemirror/utils/multiplex.js +72 -0
- data/vendor/assets/javascripts/codemirror/{overlay.js → utils/overlay.js} +3 -2
- data/vendor/assets/javascripts/codemirror/utils/pig-hint.js +123 -0
- data/vendor/assets/javascripts/codemirror/utils/runmode.js +49 -0
- data/vendor/assets/javascripts/codemirror/utils/search.js +118 -0
- data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +117 -0
- data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +72 -0
- data/vendor/assets/stylesheets/codemirror.css +69 -5
- data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +14 -21
- data/vendor/assets/stylesheets/codemirror/modes/tiki.css +26 -0
- data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +81 -0
- data/vendor/assets/stylesheets/codemirror/themes/blackboard.css +25 -0
- data/vendor/assets/stylesheets/codemirror/themes/cobalt.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/eclipse.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/elegant.css +2 -2
- data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +21 -0
- data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +44 -0
- data/vendor/assets/stylesheets/codemirror/themes/monokai.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/neat.css +3 -3
- data/vendor/assets/stylesheets/codemirror/themes/night.css +1 -1
- data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +2 -2
- data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +27 -0
- data/vendor/assets/stylesheets/codemirror/themes/xq-dark.css +46 -0
- data/vendor/assets/stylesheets/codemirror/utils/dialog.css +23 -0
- data/vendor/assets/stylesheets/codemirror/utils/simple-hint.css +16 -0
- metadata +41 -10
- data/vendor/assets/javascripts/codemirror/runmode.js +0 -27
- data/vendor/assets/stylesheets/codemirror/modes/clike.css +0 -7
- data/vendor/assets/stylesheets/codemirror/modes/markdown.css +0 -10
- data/vendor/assets/stylesheets/codemirror/modes/rst.css +0 -75
- data/vendor/assets/stylesheets/codemirror/themes/default.css +0 -19
data/README.md
CHANGED
|
@@ -35,6 +35,14 @@ Additional syntax modes can be added to your application.js:
|
|
|
35
35
|
//= require codemirror/modes/ruby
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### Adding a util
|
|
39
|
+
|
|
40
|
+
Additional reusable util components can be added in your application.js:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
//= require codemirror/utils/dialog
|
|
44
|
+
```
|
|
45
|
+
|
|
38
46
|
### Adding a keymap
|
|
39
47
|
|
|
40
48
|
Additional keymap bindings can be added to your application.js:
|
data/codemirror-rails.gemspec
CHANGED
|
@@ -3,7 +3,7 @@ require File.expand_path('../lib/codemirror/rails/version', __FILE__)
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = 'codemirror-rails'
|
|
5
5
|
s.version = Codemirror::Rails::VERSION
|
|
6
|
-
s.authors = ['Nathan Fixler']
|
|
6
|
+
s.authors = ['Nathan Fixler', 'Robin Bühler']
|
|
7
7
|
s.email = 'nathan@fixler.org'
|
|
8
8
|
s.summary = 'Use CodeMirror with Rails 3'
|
|
9
9
|
s.description = 'This gem provides CodeMirror assets for your Rails 3 application.'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// CodeMirror version 2.
|
|
1
|
+
// CodeMirror version 2.3
|
|
2
2
|
//
|
|
3
3
|
// All functions that need access to the editor's state live inside
|
|
4
4
|
// the CodeMirror function. Below that, at the bottom of the file,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
// CodeMirror is the only global var we claim
|
|
8
8
|
var CodeMirror = (function() {
|
|
9
|
-
// This is the function that produces an editor instance.
|
|
9
|
+
// This is the function that produces an editor instance. Its
|
|
10
10
|
// closure is used to store the editor state.
|
|
11
11
|
function CodeMirror(place, givenOptions) {
|
|
12
12
|
// Determine effective options based on given values and defaults.
|
|
@@ -15,24 +15,28 @@ var CodeMirror = (function() {
|
|
|
15
15
|
if (defaults.hasOwnProperty(opt))
|
|
16
16
|
options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
|
|
17
17
|
|
|
18
|
-
var targetDocument = options["document"];
|
|
19
18
|
// The element in which the editor lives.
|
|
20
|
-
var wrapper =
|
|
19
|
+
var wrapper = document.createElement("div");
|
|
21
20
|
wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
|
|
22
21
|
// This mess creates the base DOM structure for the editor.
|
|
23
22
|
wrapper.innerHTML =
|
|
24
23
|
'<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" ' +
|
|
24
|
+
'<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
|
|
26
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.
|
|
27
29
|
'<div class="CodeMirror-scroll" tabindex="-1">' +
|
|
28
30
|
'<div style="position: relative">' + // Set to the height of the text, causes scrolling
|
|
29
31
|
'<div style="position: relative">' + // Moved around its parent to cover visible view
|
|
30
32
|
'<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
|
|
31
33
|
// Provides positioning relative to (visible) text origin
|
|
32
|
-
'<div class="CodeMirror-lines"><div style="position: relative">' +
|
|
33
|
-
|
|
34
|
+
'<div class="CodeMirror-lines"><div style="position: relative; z-index: 0">' +
|
|
35
|
+
// Used to measure text size
|
|
36
|
+
'<div style="position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden;"></div>' +
|
|
34
37
|
'<pre class="CodeMirror-cursor"> </pre>' + // Absolutely positioned blinky cursor
|
|
35
|
-
'<
|
|
38
|
+
'<pre class="CodeMirror-cursor" style="visibility: hidden"> </pre>' + // Used to force a width
|
|
39
|
+
'<div style="position: relative; z-index: -1"></div><div></div>' + // DIVs containing the selection and the actual code
|
|
36
40
|
'</div></div></div></div></div>';
|
|
37
41
|
if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
|
|
38
42
|
// I've never seen more elegant code in my life.
|
|
@@ -40,13 +44,30 @@ var CodeMirror = (function() {
|
|
|
40
44
|
scroller = wrapper.lastChild, code = scroller.firstChild,
|
|
41
45
|
mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
|
|
42
46
|
lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
|
|
43
|
-
cursor = measure.nextSibling,
|
|
44
|
-
|
|
47
|
+
cursor = measure.nextSibling, widthForcer = cursor.nextSibling,
|
|
48
|
+
selectionDiv = widthForcer.nextSibling, lineDiv = selectionDiv.nextSibling,
|
|
49
|
+
scrollbar = inputDiv.nextSibling, scrollbarInner = scrollbar.firstChild;
|
|
50
|
+
themeChanged(); keyMapChanged();
|
|
45
51
|
// Needed to hide big blue blinking cursor on Mobile Safari
|
|
46
|
-
if (
|
|
47
|
-
if (!webkit)
|
|
52
|
+
if (ios) input.style.width = "0px";
|
|
53
|
+
if (!webkit) scroller.draggable = true;
|
|
54
|
+
lineSpace.style.outline = "none";
|
|
48
55
|
if (options.tabindex != null) input.tabIndex = options.tabindex;
|
|
56
|
+
if (options.autofocus) focusInput();
|
|
49
57
|
if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
|
|
58
|
+
// Needed to handle Tab key in KHTML
|
|
59
|
+
if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute";
|
|
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
|
+
}
|
|
50
71
|
|
|
51
72
|
// Check for problem with IE innerHTML not working when we have a
|
|
52
73
|
// P (or similar) parent node.
|
|
@@ -71,19 +92,21 @@ var CodeMirror = (function() {
|
|
|
71
92
|
var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
|
|
72
93
|
// Selection-related flags. shiftSelecting obviously tracks
|
|
73
94
|
// whether the user is holding shift.
|
|
74
|
-
var shiftSelecting, lastClick, lastDoubleClick,
|
|
95
|
+
var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, lastScrollLeft = 0, draggingText,
|
|
96
|
+
overwrite = false, suppressEdits = false;
|
|
75
97
|
// Variables used by startOperation/endOperation to track what
|
|
76
98
|
// happened during the operation.
|
|
77
99
|
var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
|
|
78
100
|
gutterDirty, callbacks;
|
|
79
101
|
// Current visible range (may be bigger than the view window).
|
|
80
102
|
var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
|
|
81
|
-
// bracketHighlighted is used to remember that a
|
|
103
|
+
// bracketHighlighted is used to remember that a bracket has been
|
|
82
104
|
// marked.
|
|
83
105
|
var bracketHighlighted;
|
|
84
106
|
// Tracks the maximum line length so that the horizontal scrollbar
|
|
85
107
|
// can be kept static when scrolling.
|
|
86
|
-
var maxLine = "",
|
|
108
|
+
var maxLine = "", updateMaxLine = false, maxLineChanged = true;
|
|
109
|
+
var tabCache = {};
|
|
87
110
|
|
|
88
111
|
// Initialize the content.
|
|
89
112
|
operation(function(){setValue(options.value || ""); updateInput = false;})();
|
|
@@ -92,17 +115,16 @@ var CodeMirror = (function() {
|
|
|
92
115
|
// Register our event handlers.
|
|
93
116
|
connect(scroller, "mousedown", operation(onMouseDown));
|
|
94
117
|
connect(scroller, "dblclick", operation(onDoubleClick));
|
|
95
|
-
connect(lineSpace, "dragstart", onDragStart);
|
|
96
118
|
connect(lineSpace, "selectstart", e_preventDefault);
|
|
97
119
|
// Gecko browsers fire contextmenu *after* opening the menu, at
|
|
98
120
|
// which point we can't mess with it anymore. Context menu is
|
|
99
121
|
// handled in onMouseDown for Gecko.
|
|
100
122
|
if (!gecko) connect(scroller, "contextmenu", onContextMenu);
|
|
101
|
-
connect(scroller, "scroll",
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
123
|
+
connect(scroller, "scroll", onScroll);
|
|
124
|
+
connect(scrollbar, "scroll", onScroll);
|
|
125
|
+
connect(scrollbar, "mousedown", function() {setTimeout(focusInput, 0);});
|
|
126
|
+
connect(scroller, "mousewheel", onMouseWheel);
|
|
127
|
+
connect(scroller, "DOMMouseScroll", onMouseWheel);
|
|
106
128
|
connect(window, "resize", function() {updateDisplay(true);});
|
|
107
129
|
connect(input, "keyup", operation(onKeyUp));
|
|
108
130
|
connect(input, "input", fastPoll);
|
|
@@ -111,17 +133,32 @@ var CodeMirror = (function() {
|
|
|
111
133
|
connect(input, "focus", onFocus);
|
|
112
134
|
connect(input, "blur", onBlur);
|
|
113
135
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
if (options.dragDrop) {
|
|
137
|
+
connect(scroller, "dragstart", onDragStart);
|
|
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
|
+
}
|
|
117
146
|
connect(scroller, "paste", function(){focusInput(); fastPoll();});
|
|
118
147
|
connect(input, "paste", fastPoll);
|
|
119
|
-
connect(input, "cut", operation(function(){
|
|
148
|
+
connect(input, "cut", operation(function(){
|
|
149
|
+
if (!options.readOnly) replaceSelection("");
|
|
150
|
+
}));
|
|
151
|
+
|
|
152
|
+
// Needed to handle Tab key in KHTML
|
|
153
|
+
if (khtml) connect(code, "mouseup", function() {
|
|
154
|
+
if (document.activeElement == input) input.blur();
|
|
155
|
+
focusInput();
|
|
156
|
+
});
|
|
120
157
|
|
|
121
158
|
// IE throws unspecified error in certain cases, when
|
|
122
159
|
// trying to access activeElement before onload
|
|
123
|
-
var hasFocus; try { hasFocus = (
|
|
124
|
-
if (hasFocus) setTimeout(onFocus, 20);
|
|
160
|
+
var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { }
|
|
161
|
+
if (hasFocus || options.autofocus) setTimeout(onFocus, 20);
|
|
125
162
|
else onBlur();
|
|
126
163
|
|
|
127
164
|
function isLine(l) {return l >= 0 && l < doc.size;}
|
|
@@ -135,23 +172,31 @@ var CodeMirror = (function() {
|
|
|
135
172
|
setValue: operation(setValue),
|
|
136
173
|
getSelection: getSelection,
|
|
137
174
|
replaceSelection: operation(replaceSelection),
|
|
138
|
-
focus: function(){focusInput(); onFocus(); fastPoll();},
|
|
175
|
+
focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},
|
|
139
176
|
setOption: function(option, value) {
|
|
140
177
|
var oldVal = options[option];
|
|
141
178
|
options[option] = value;
|
|
142
179
|
if (option == "mode" || option == "indentUnit") loadMode();
|
|
143
|
-
else if (option == "readOnly" && value) {onBlur(); input.blur();}
|
|
180
|
+
else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();}
|
|
181
|
+
else if (option == "readOnly" && !value) {resetInput(true);}
|
|
144
182
|
else if (option == "theme") themeChanged();
|
|
145
183
|
else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
|
|
146
|
-
else if (option == "tabSize")
|
|
147
|
-
if (option == "
|
|
148
|
-
|
|
184
|
+
else if (option == "tabSize") updateDisplay(true);
|
|
185
|
+
else if (option == "keyMap") keyMapChanged();
|
|
186
|
+
if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
|
|
187
|
+
gutterChanged();
|
|
188
|
+
updateDisplay(true);
|
|
189
|
+
}
|
|
149
190
|
},
|
|
150
191
|
getOption: function(option) {return options[option];},
|
|
151
192
|
undo: operation(undo),
|
|
152
193
|
redo: operation(redo),
|
|
153
194
|
indentLine: operation(function(n, dir) {
|
|
154
|
-
if (
|
|
195
|
+
if (typeof dir != "string") {
|
|
196
|
+
if (dir == null) dir = options.smartIndent ? "smart" : "prev";
|
|
197
|
+
else dir = dir ? "add" : "subtract";
|
|
198
|
+
}
|
|
199
|
+
if (isLine(n)) indentLine(n, dir);
|
|
155
200
|
}),
|
|
156
201
|
indentSelection: operation(indentSelected),
|
|
157
202
|
historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
|
|
@@ -165,17 +210,23 @@ var CodeMirror = (function() {
|
|
|
165
210
|
line = clipLine(line == null ? doc.size - 1: line);
|
|
166
211
|
return getStateBefore(line + 1);
|
|
167
212
|
},
|
|
168
|
-
cursorCoords: function(start){
|
|
213
|
+
cursorCoords: function(start, mode) {
|
|
169
214
|
if (start == null) start = sel.inverted;
|
|
170
|
-
return
|
|
215
|
+
return this.charCoords(start ? sel.from : sel.to, mode);
|
|
216
|
+
},
|
|
217
|
+
charCoords: function(pos, mode) {
|
|
218
|
+
pos = clipPos(pos);
|
|
219
|
+
if (mode == "local") return localCoords(pos, false);
|
|
220
|
+
if (mode == "div") return localCoords(pos, true);
|
|
221
|
+
return pageCoords(pos);
|
|
171
222
|
},
|
|
172
|
-
charCoords: function(pos){return pageCoords(clipPos(pos));},
|
|
173
223
|
coordsChar: function(coords) {
|
|
174
224
|
var off = eltOffset(lineSpace);
|
|
175
225
|
return coordsChar(coords.x - off.left, coords.y - off.top);
|
|
176
226
|
},
|
|
177
227
|
markText: operation(markText),
|
|
178
228
|
setBookmark: setBookmark,
|
|
229
|
+
findMarksAt: findMarksAt,
|
|
179
230
|
setMarker: operation(addGutterMarker),
|
|
180
231
|
clearMarker: operation(removeGutterMarker),
|
|
181
232
|
setLineClass: operation(setLineClass),
|
|
@@ -243,12 +294,21 @@ var CodeMirror = (function() {
|
|
|
243
294
|
replaceRange: operation(replaceRange),
|
|
244
295
|
getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},
|
|
245
296
|
|
|
297
|
+
triggerOnKeyDown: operation(onKeyDown),
|
|
246
298
|
execCommand: function(cmd) {return commands[cmd](instance);},
|
|
247
299
|
// Stuff used by commands, probably not much use to outside code.
|
|
248
300
|
moveH: operation(moveH),
|
|
249
301
|
deleteH: operation(deleteH),
|
|
250
302
|
moveV: operation(moveV),
|
|
251
|
-
toggleOverwrite: function() {
|
|
303
|
+
toggleOverwrite: function() {
|
|
304
|
+
if(overwrite){
|
|
305
|
+
overwrite = false;
|
|
306
|
+
cursor.className = cursor.className.replace(" CodeMirror-overwrite", "");
|
|
307
|
+
} else {
|
|
308
|
+
overwrite = true;
|
|
309
|
+
cursor.className += " CodeMirror-overwrite";
|
|
310
|
+
}
|
|
311
|
+
},
|
|
252
312
|
|
|
253
313
|
posFromIndex: function(off) {
|
|
254
314
|
var lineNo = 0, ch;
|
|
@@ -268,9 +328,23 @@ var CodeMirror = (function() {
|
|
|
268
328
|
});
|
|
269
329
|
return index;
|
|
270
330
|
},
|
|
331
|
+
scrollTo: function(x, y) {
|
|
332
|
+
if (x != null) scroller.scrollLeft = x;
|
|
333
|
+
if (y != null) scrollbar.scrollTop = y;
|
|
334
|
+
updateDisplay([]);
|
|
335
|
+
},
|
|
336
|
+
getScrollInfo: function() {
|
|
337
|
+
return {x: scroller.scrollLeft, y: scrollbar.scrollTop,
|
|
338
|
+
height: scrollbar.scrollHeight, width: scroller.scrollWidth};
|
|
339
|
+
},
|
|
271
340
|
|
|
272
341
|
operation: function(f){return operation(f)();},
|
|
273
|
-
|
|
342
|
+
compoundChange: function(f){return compoundChange(f);},
|
|
343
|
+
refresh: function(){
|
|
344
|
+
updateDisplay(true);
|
|
345
|
+
if (scrollbar.scrollHeight > lastScrollTop)
|
|
346
|
+
scrollbar.scrollTop = lastScrollTop;
|
|
347
|
+
},
|
|
274
348
|
getInputField: function(){return input;},
|
|
275
349
|
getWrapperElement: function(){return wrapper;},
|
|
276
350
|
getScrollerElement: function(){return scroller;},
|
|
@@ -290,14 +364,24 @@ var CodeMirror = (function() {
|
|
|
290
364
|
splitLines(code), top, top);
|
|
291
365
|
updateInput = true;
|
|
292
366
|
}
|
|
293
|
-
function getValue(
|
|
367
|
+
function getValue() {
|
|
294
368
|
var text = [];
|
|
295
369
|
doc.iter(0, doc.size, function(line) { text.push(line.text); });
|
|
296
370
|
return text.join("\n");
|
|
297
371
|
}
|
|
298
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
|
+
|
|
299
383
|
function onMouseDown(e) {
|
|
300
|
-
setShift(e
|
|
384
|
+
setShift(e_prop(e, "shiftKey"));
|
|
301
385
|
// Check whether this is a click in a widget
|
|
302
386
|
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
|
303
387
|
if (n.parentNode == code && n != mover) return;
|
|
@@ -318,6 +402,8 @@ var CodeMirror = (function() {
|
|
|
318
402
|
return;
|
|
319
403
|
case 2:
|
|
320
404
|
if (start) setCursor(start.line, start.ch, true);
|
|
405
|
+
setTimeout(focusInput, 20);
|
|
406
|
+
e_preventDefault(e);
|
|
321
407
|
return;
|
|
322
408
|
}
|
|
323
409
|
// For button 1, if it was clicked inside the editor
|
|
@@ -339,21 +425,25 @@ var CodeMirror = (function() {
|
|
|
339
425
|
} else { lastClick = {time: now, pos: start}; }
|
|
340
426
|
|
|
341
427
|
var last = start, going;
|
|
342
|
-
if (dragAndDrop && !posEq(sel.from, sel.to) &&
|
|
428
|
+
if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
|
|
343
429
|
!posLess(start, sel.from) && !posLess(sel.to, start)) {
|
|
344
430
|
// Let the drag handler handle this.
|
|
345
|
-
if (webkit)
|
|
346
|
-
|
|
347
|
-
if (webkit)
|
|
431
|
+
if (webkit) scroller.draggable = true;
|
|
432
|
+
function dragEnd(e2) {
|
|
433
|
+
if (webkit) scroller.draggable = false;
|
|
348
434
|
draggingText = false;
|
|
349
|
-
up();
|
|
435
|
+
up(); drop();
|
|
350
436
|
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
|
|
351
437
|
e_preventDefault(e2);
|
|
352
438
|
setCursor(start.line, start.ch, true);
|
|
353
439
|
focusInput();
|
|
354
440
|
}
|
|
355
|
-
}
|
|
441
|
+
}
|
|
442
|
+
var up = connect(document, "mouseup", operation(dragEnd), true);
|
|
443
|
+
var drop = connect(scroller, "drop", operation(dragEnd), true);
|
|
356
444
|
draggingText = true;
|
|
445
|
+
// IE's approach to draggable
|
|
446
|
+
if (scroller.dragDrop) scroller.dragDrop();
|
|
357
447
|
return;
|
|
358
448
|
}
|
|
359
449
|
e_preventDefault(e);
|
|
@@ -372,12 +462,7 @@ var CodeMirror = (function() {
|
|
|
372
462
|
}
|
|
373
463
|
}
|
|
374
464
|
|
|
375
|
-
|
|
376
|
-
clearTimeout(going);
|
|
377
|
-
e_preventDefault(e);
|
|
378
|
-
extend(e);
|
|
379
|
-
}), true);
|
|
380
|
-
var up = connect(targetDocument, "mouseup", operation(function(e) {
|
|
465
|
+
function done(e) {
|
|
381
466
|
clearTimeout(going);
|
|
382
467
|
var cur = posFromMouse(e);
|
|
383
468
|
if (cur) setSelectionUser(start, cur);
|
|
@@ -385,7 +470,14 @@ var CodeMirror = (function() {
|
|
|
385
470
|
focusInput();
|
|
386
471
|
updateInput = true;
|
|
387
472
|
move(); up();
|
|
473
|
+
}
|
|
474
|
+
var move = connect(document, "mousemove", operation(function(e) {
|
|
475
|
+
clearTimeout(going);
|
|
476
|
+
e_preventDefault(e);
|
|
477
|
+
if (!ie && !e_button(e)) done(e);
|
|
478
|
+
else extend(e);
|
|
388
479
|
}), true);
|
|
480
|
+
var up = connect(document, "mouseup", operation(done), true);
|
|
389
481
|
}
|
|
390
482
|
function onDoubleClick(e) {
|
|
391
483
|
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
|
@@ -397,6 +489,7 @@ var CodeMirror = (function() {
|
|
|
397
489
|
selectWordAt(start);
|
|
398
490
|
}
|
|
399
491
|
function onDrop(e) {
|
|
492
|
+
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
|
|
400
493
|
e.preventDefault();
|
|
401
494
|
var pos = posFromMouse(e, true), files = e.dataTransfer.files;
|
|
402
495
|
if (!pos || options.readOnly) return;
|
|
@@ -406,108 +499,156 @@ var CodeMirror = (function() {
|
|
|
406
499
|
reader.onload = function() {
|
|
407
500
|
text[i] = reader.result;
|
|
408
501
|
if (++read == n) {
|
|
409
|
-
|
|
410
|
-
|
|
502
|
+
pos = clipPos(pos);
|
|
503
|
+
operation(function() {
|
|
411
504
|
var end = replaceRange(text.join(""), pos, pos);
|
|
412
505
|
setSelectionUser(pos, end);
|
|
413
506
|
})();
|
|
414
|
-
|
|
507
|
+
}
|
|
415
508
|
};
|
|
416
509
|
reader.readAsText(file);
|
|
417
510
|
}
|
|
418
511
|
var n = files.length, text = Array(n), read = 0;
|
|
419
512
|
for (var i = 0; i < n; ++i) loadFile(files[i], i);
|
|
420
|
-
}
|
|
421
|
-
|
|
513
|
+
} else {
|
|
514
|
+
// Don't do a replace if the drop happened inside of the selected text.
|
|
515
|
+
if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) return;
|
|
422
516
|
try {
|
|
423
517
|
var text = e.dataTransfer.getData("Text");
|
|
424
518
|
if (text) {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
519
|
+
compoundChange(function() {
|
|
520
|
+
var curFrom = sel.from, curTo = sel.to;
|
|
521
|
+
setSelectionUser(pos, pos);
|
|
522
|
+
if (draggingText) replaceRange("", curFrom, curTo);
|
|
523
|
+
replaceSelection(text);
|
|
524
|
+
focusInput();
|
|
525
|
+
});
|
|
526
|
+
}
|
|
431
527
|
}
|
|
432
528
|
catch(e){}
|
|
433
529
|
}
|
|
434
530
|
}
|
|
435
531
|
function onDragStart(e) {
|
|
436
532
|
var txt = getSelection();
|
|
437
|
-
// This will reset escapeElement
|
|
438
|
-
htmlEscape(txt);
|
|
439
|
-
e.dataTransfer.setDragImage(escapeElement, 0, 0);
|
|
440
533
|
e.dataTransfer.setData("Text", txt);
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
if (e.altKey) name = "Alt-" + name;
|
|
449
|
-
if (e.ctrlKey) name = "Ctrl-" + name;
|
|
450
|
-
if (e.metaKey) name = "Cmd-" + name;
|
|
451
|
-
if (e.shiftKey && (bound = lookupKey("Shift-" + name, options.extraKeys, options.keyMap))) {
|
|
452
|
-
dropShift = true;
|
|
453
|
-
} else {
|
|
454
|
-
bound = lookupKey(name, options.extraKeys, options.keyMap);
|
|
534
|
+
|
|
535
|
+
// Use dummy image instead of default browsers image.
|
|
536
|
+
if (gecko || chrome || opera) {
|
|
537
|
+
var img = document.createElement('img');
|
|
538
|
+
img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image
|
|
539
|
+
e.dataTransfer.setDragImage(img, 0, 0);
|
|
455
540
|
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function doHandleBinding(bound, dropShift) {
|
|
456
544
|
if (typeof bound == "string") {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
shiftSelecting = null;
|
|
545
|
+
bound = commands[bound];
|
|
546
|
+
if (!bound) return false;
|
|
547
|
+
}
|
|
548
|
+
var prevShift = shiftSelecting;
|
|
549
|
+
try {
|
|
550
|
+
if (options.readOnly) suppressEdits = true;
|
|
551
|
+
if (dropShift) shiftSelecting = null;
|
|
465
552
|
bound(instance);
|
|
553
|
+
} catch(e) {
|
|
554
|
+
if (e != Pass) throw e;
|
|
555
|
+
return false;
|
|
556
|
+
} finally {
|
|
466
557
|
shiftSelecting = prevShift;
|
|
467
|
-
|
|
468
|
-
|
|
558
|
+
suppressEdits = false;
|
|
559
|
+
}
|
|
469
560
|
return true;
|
|
470
561
|
}
|
|
471
|
-
|
|
562
|
+
function handleKeyBinding(e) {
|
|
563
|
+
// Handle auto keymap transitions
|
|
564
|
+
var startMap = getKeyMap(options.keyMap), next = startMap.auto;
|
|
565
|
+
clearTimeout(maybeTransition);
|
|
566
|
+
if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
|
|
567
|
+
if (getKeyMap(options.keyMap) == startMap) {
|
|
568
|
+
options.keyMap = (next.call ? next.call(null, instance) : next);
|
|
569
|
+
}
|
|
570
|
+
}, 50);
|
|
571
|
+
|
|
572
|
+
var name = keyNames[e_prop(e, "keyCode")], handled = false;
|
|
573
|
+
if (name == null || e.altGraphKey) return false;
|
|
574
|
+
if (e_prop(e, "altKey")) name = "Alt-" + name;
|
|
575
|
+
if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
|
|
576
|
+
if (e_prop(e, "metaKey")) name = "Cmd-" + name;
|
|
577
|
+
|
|
578
|
+
var stopped = false;
|
|
579
|
+
function stop() { stopped = true; }
|
|
580
|
+
|
|
581
|
+
if (e_prop(e, "shiftKey")) {
|
|
582
|
+
handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
|
|
583
|
+
function(b) {return doHandleBinding(b, true);}, stop)
|
|
584
|
+
|| lookupKey(name, options.extraKeys, options.keyMap, function(b) {
|
|
585
|
+
if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b);
|
|
586
|
+
}, stop);
|
|
587
|
+
} else {
|
|
588
|
+
handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);
|
|
589
|
+
}
|
|
590
|
+
if (stopped) handled = false;
|
|
591
|
+
if (handled) {
|
|
592
|
+
e_preventDefault(e);
|
|
593
|
+
restartBlink();
|
|
594
|
+
if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
|
|
595
|
+
}
|
|
596
|
+
return handled;
|
|
597
|
+
}
|
|
598
|
+
function handleCharBinding(e, ch) {
|
|
599
|
+
var handled = lookupKey("'" + ch + "'", options.extraKeys,
|
|
600
|
+
options.keyMap, function(b) { return doHandleBinding(b, true); });
|
|
601
|
+
if (handled) {
|
|
602
|
+
e_preventDefault(e);
|
|
603
|
+
restartBlink();
|
|
604
|
+
}
|
|
605
|
+
return handled;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
var lastStoppedKey = null, maybeTransition;
|
|
472
609
|
function onKeyDown(e) {
|
|
473
610
|
if (!focused) onFocus();
|
|
474
|
-
|
|
611
|
+
if (ie && e.keyCode == 27) { e.returnValue = false; }
|
|
612
|
+
if (pollingFast) { if (readInput()) pollingFast = false; }
|
|
613
|
+
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
614
|
+
var code = e_prop(e, "keyCode");
|
|
475
615
|
// IE does strange things with escape.
|
|
476
|
-
|
|
477
|
-
setShift(code == 16 || e.shiftKey);
|
|
616
|
+
setShift(code == 16 || e_prop(e, "shiftKey"));
|
|
478
617
|
// First give onKeyEvent option a chance to handle this.
|
|
479
|
-
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
480
618
|
var handled = handleKeyBinding(e);
|
|
481
|
-
if (
|
|
482
|
-
lastStoppedKey = handled ?
|
|
619
|
+
if (opera) {
|
|
620
|
+
lastStoppedKey = handled ? code : null;
|
|
483
621
|
// Opera has no cut event... we try to at least catch the key combo
|
|
484
|
-
if (!handled && (mac ?
|
|
622
|
+
if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey"))
|
|
485
623
|
replaceSelection("");
|
|
486
624
|
}
|
|
487
625
|
}
|
|
488
626
|
function onKeyPress(e) {
|
|
489
|
-
if (
|
|
627
|
+
if (pollingFast) readInput();
|
|
490
628
|
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
491
|
-
|
|
492
|
-
if (
|
|
493
|
-
|
|
629
|
+
var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
|
|
630
|
+
if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
|
|
631
|
+
if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;
|
|
632
|
+
var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
|
|
633
|
+
if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
|
|
494
634
|
if (mode.electricChars.indexOf(ch) > -1)
|
|
495
635
|
setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75);
|
|
496
636
|
}
|
|
637
|
+
if (handleCharBinding(e, ch)) return;
|
|
497
638
|
fastPoll();
|
|
498
639
|
}
|
|
499
640
|
function onKeyUp(e) {
|
|
500
641
|
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
|
|
501
|
-
if (e
|
|
642
|
+
if (e_prop(e, "keyCode") == 16) shiftSelecting = null;
|
|
502
643
|
}
|
|
503
644
|
|
|
504
645
|
function onFocus() {
|
|
505
|
-
if (options.readOnly) return;
|
|
646
|
+
if (options.readOnly == "nocursor") return;
|
|
506
647
|
if (!focused) {
|
|
507
648
|
if (options.onFocus) options.onFocus(instance);
|
|
508
649
|
focused = true;
|
|
509
|
-
if (
|
|
510
|
-
|
|
650
|
+
if (scroller.className.search(/\bCodeMirror-focused\b/) == -1)
|
|
651
|
+
scroller.className += " CodeMirror-focused";
|
|
511
652
|
if (!leaveInputAlone) resetInput(true);
|
|
512
653
|
}
|
|
513
654
|
slowPoll();
|
|
@@ -517,15 +658,56 @@ var CodeMirror = (function() {
|
|
|
517
658
|
if (focused) {
|
|
518
659
|
if (options.onBlur) options.onBlur(instance);
|
|
519
660
|
focused = false;
|
|
520
|
-
|
|
661
|
+
if (bracketHighlighted)
|
|
662
|
+
operation(function(){
|
|
663
|
+
if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }
|
|
664
|
+
})();
|
|
665
|
+
scroller.className = scroller.className.replace(" CodeMirror-focused", "");
|
|
521
666
|
}
|
|
522
667
|
clearInterval(blinker);
|
|
523
668
|
setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
|
|
524
669
|
}
|
|
525
670
|
|
|
671
|
+
function chopDelta(delta) {
|
|
672
|
+
// Make sure we always scroll a little bit for any nonzero delta.
|
|
673
|
+
if (delta > 0.0 && delta < 1.0) return 1;
|
|
674
|
+
else if (delta > -1.0 && delta < 0.0) return -1;
|
|
675
|
+
else return Math.round(delta);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
function onMouseWheel(e) {
|
|
679
|
+
var deltaX = 0, deltaY = 0;
|
|
680
|
+
if (e.type == "DOMMouseScroll") { // Firefox
|
|
681
|
+
var delta = -e.detail * 8.0;
|
|
682
|
+
if (e.axis == e.HORIZONTAL_AXIS) deltaX = delta;
|
|
683
|
+
else if (e.axis == e.VERTICAL_AXIS) deltaY = delta;
|
|
684
|
+
} else if (e.wheelDeltaX !== undefined && e.wheelDeltaY !== undefined) { // WebKit
|
|
685
|
+
deltaX = e.wheelDeltaX / 3.0;
|
|
686
|
+
deltaY = e.wheelDeltaY / 3.0;
|
|
687
|
+
} else if (e.wheelDelta !== undefined) { // IE or Opera
|
|
688
|
+
deltaY = e.wheelDelta / 3.0;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
var scrolled = false;
|
|
692
|
+
deltaX = chopDelta(deltaX);
|
|
693
|
+
deltaY = chopDelta(deltaY);
|
|
694
|
+
if ((deltaX > 0 && scroller.scrollLeft > 0) ||
|
|
695
|
+
(deltaX < 0 && scroller.scrollLeft + scroller.clientWidth < scroller.scrollWidth)) {
|
|
696
|
+
scroller.scrollLeft -= deltaX;
|
|
697
|
+
scrolled = true;
|
|
698
|
+
}
|
|
699
|
+
if ((deltaY > 0 && scrollbar.scrollTop > 0) ||
|
|
700
|
+
(deltaY < 0 && scrollbar.scrollTop + scrollbar.clientHeight < scrollbar.scrollHeight)) {
|
|
701
|
+
scrollbar.scrollTop -= deltaY;
|
|
702
|
+
scrolled = true;
|
|
703
|
+
}
|
|
704
|
+
if (scrolled) e_stop(e);
|
|
705
|
+
}
|
|
706
|
+
|
|
526
707
|
// Replace the range from from to to by the strings in newText.
|
|
527
708
|
// Afterwards, set the selection to selFrom, selTo.
|
|
528
709
|
function updateLines(from, to, newText, selFrom, selTo) {
|
|
710
|
+
if (suppressEdits) return;
|
|
529
711
|
if (history) {
|
|
530
712
|
var old = [];
|
|
531
713
|
doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });
|
|
@@ -535,25 +717,29 @@ var CodeMirror = (function() {
|
|
|
535
717
|
updateLinesNoUndo(from, to, newText, selFrom, selTo);
|
|
536
718
|
}
|
|
537
719
|
function unredoHelper(from, to) {
|
|
538
|
-
|
|
539
|
-
|
|
720
|
+
if (!from.length) return;
|
|
721
|
+
var set = from.pop(), out = [];
|
|
722
|
+
for (var i = set.length - 1; i >= 0; i -= 1) {
|
|
723
|
+
var change = set[i];
|
|
540
724
|
var replaced = [], end = change.start + change.added;
|
|
541
725
|
doc.iter(change.start, end, function(line) { replaced.push(line.text); });
|
|
542
|
-
|
|
543
|
-
var pos =
|
|
544
|
-
|
|
726
|
+
out.push({start: change.start, added: change.old.length, old: replaced});
|
|
727
|
+
var pos = {line: change.start + change.old.length - 1,
|
|
728
|
+
ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])};
|
|
545
729
|
updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);
|
|
546
|
-
updateInput = true;
|
|
547
730
|
}
|
|
731
|
+
updateInput = true;
|
|
732
|
+
to.push(out);
|
|
548
733
|
}
|
|
549
734
|
function undo() {unredoHelper(history.done, history.undone);}
|
|
550
735
|
function redo() {unredoHelper(history.undone, history.done);}
|
|
551
736
|
|
|
552
737
|
function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
|
|
738
|
+
if (suppressEdits) return;
|
|
553
739
|
var recomputeMaxLength = false, maxLineLength = maxLine.length;
|
|
554
740
|
if (!options.lineWrapping)
|
|
555
|
-
doc.iter(from.line, to.line, function(line) {
|
|
556
|
-
if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
|
|
741
|
+
doc.iter(from.line, to.line + 1, function(line) {
|
|
742
|
+
if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
|
|
557
743
|
});
|
|
558
744
|
if (from.line != to.line || newText.length > 1) gutterDirty = true;
|
|
559
745
|
|
|
@@ -600,29 +786,21 @@ var CodeMirror = (function() {
|
|
|
600
786
|
doc.insert(from.line + 1, added);
|
|
601
787
|
}
|
|
602
788
|
if (options.lineWrapping) {
|
|
603
|
-
var perLine = scroller.clientWidth / charWidth() - 3;
|
|
789
|
+
var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);
|
|
604
790
|
doc.iter(from.line, from.line + newText.length, function(line) {
|
|
605
791
|
if (line.hidden) return;
|
|
606
792
|
var guess = Math.ceil(line.text.length / perLine) || 1;
|
|
607
793
|
if (guess != line.height) updateLineHeight(line, guess);
|
|
608
794
|
});
|
|
609
795
|
} else {
|
|
610
|
-
doc.iter(from.line,
|
|
796
|
+
doc.iter(from.line, from.line + newText.length, function(line) {
|
|
611
797
|
var l = line.text;
|
|
612
|
-
if (l.length > maxLineLength) {
|
|
613
|
-
maxLine = l; maxLineLength = l.length;
|
|
798
|
+
if (!line.hidden && l.length > maxLineLength) {
|
|
799
|
+
maxLine = l; maxLineLength = l.length; maxLineChanged = true;
|
|
614
800
|
recomputeMaxLength = false;
|
|
615
801
|
}
|
|
616
802
|
});
|
|
617
|
-
if (recomputeMaxLength)
|
|
618
|
-
maxLineLength = 0; maxLine = ""; maxWidth = null;
|
|
619
|
-
doc.iter(0, doc.size, function(line) {
|
|
620
|
-
var l = line.text;
|
|
621
|
-
if (l.length > maxLineLength) {
|
|
622
|
-
maxLineLength = l.length; maxLine = l;
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
}
|
|
803
|
+
if (recomputeMaxLength) updateMaxLine = true;
|
|
626
804
|
}
|
|
627
805
|
|
|
628
806
|
// Add these lines to the work array, so that they will be
|
|
@@ -648,10 +826,49 @@ var CodeMirror = (function() {
|
|
|
648
826
|
|
|
649
827
|
// Update the selection
|
|
650
828
|
function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}
|
|
651
|
-
setSelection(selFrom, selTo
|
|
829
|
+
setSelection(clipPos(selFrom), clipPos(selTo),
|
|
830
|
+
updateLine(sel.from.line), updateLine(sel.to.line));
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function updateVerticalScroll(scrollTop) {
|
|
834
|
+
var th = textHeight(), virtualHeight = Math.floor(doc.height * th + 2 * paddingTop()), scrollbarHeight = scroller.clientHeight;
|
|
835
|
+
scrollbar.style.height = scrollbarHeight + "px";
|
|
836
|
+
if (scroller.clientHeight)
|
|
837
|
+
scrollbarInner.style.height = virtualHeight + "px";
|
|
838
|
+
// Position the mover div to align with the current virtual scroll position
|
|
839
|
+
if (scrollTop != null) scrollbar.scrollTop = scrollTop;
|
|
840
|
+
mover.style.top = (displayOffset * th - scrollbar.scrollTop) + "px";
|
|
841
|
+
scrollbar.style.display = (virtualHeight > scrollbarHeight) ? "block" : "none";
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// On Mac OS X Lion and up, detect whether the mouse is plugged in by measuring
|
|
845
|
+
// the width of a div with a scrollbar in it. If the width is <= 1, then
|
|
846
|
+
// the mouse isn't plugged in and scrollbars should overlap the content.
|
|
847
|
+
function overlapScrollbars() {
|
|
848
|
+
var tmpSb = document.createElement('div'),
|
|
849
|
+
tmpSbInner = document.createElement('div');
|
|
850
|
+
tmpSb.className = "CodeMirror-scrollbar";
|
|
851
|
+
tmpSb.style.cssText = "position: absolute; left: -9999px; height: 100px;";
|
|
852
|
+
tmpSbInner.className = "CodeMirror-scrollbar-inner";
|
|
853
|
+
tmpSbInner.style.height = "200px";
|
|
854
|
+
tmpSb.appendChild(tmpSbInner);
|
|
855
|
+
|
|
856
|
+
document.body.appendChild(tmpSb);
|
|
857
|
+
var result = (tmpSb.offsetWidth <= 1);
|
|
858
|
+
document.body.removeChild(tmpSb);
|
|
859
|
+
return result;
|
|
860
|
+
}
|
|
652
861
|
|
|
653
|
-
|
|
654
|
-
|
|
862
|
+
function computeMaxLength() {
|
|
863
|
+
var maxLineLength = 0;
|
|
864
|
+
maxLine = ""; maxLineChanged = true;
|
|
865
|
+
doc.iter(0, doc.size, function(line) {
|
|
866
|
+
var l = line.text;
|
|
867
|
+
if (!line.hidden && l.length > maxLineLength) {
|
|
868
|
+
maxLineLength = l.length; maxLine = l;
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
updateMaxLine = false;
|
|
655
872
|
}
|
|
656
873
|
|
|
657
874
|
function replaceRange(code, from, to) {
|
|
@@ -729,7 +946,7 @@ var CodeMirror = (function() {
|
|
|
729
946
|
// supported or compatible enough yet to rely on.)
|
|
730
947
|
var prevInput = "";
|
|
731
948
|
function readInput() {
|
|
732
|
-
if (leaveInputAlone || !focused || hasSelection(input)) return false;
|
|
949
|
+
if (leaveInputAlone || !focused || hasSelection(input) || options.readOnly) return false;
|
|
733
950
|
var text = input.value;
|
|
734
951
|
if (text == prevInput) return false;
|
|
735
952
|
shiftSelecting = null;
|
|
@@ -740,19 +957,20 @@ var CodeMirror = (function() {
|
|
|
740
957
|
else if (overwrite && posEq(sel.from, sel.to))
|
|
741
958
|
sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
|
|
742
959
|
replaceSelection(text.slice(same), "end");
|
|
743
|
-
prevInput =
|
|
960
|
+
if (text.length > 1000) { input.value = prevInput = ""; }
|
|
961
|
+
else prevInput = text;
|
|
744
962
|
return true;
|
|
745
963
|
}
|
|
746
964
|
function resetInput(user) {
|
|
747
965
|
if (!posEq(sel.from, sel.to)) {
|
|
748
966
|
prevInput = "";
|
|
749
967
|
input.value = getSelection();
|
|
750
|
-
input
|
|
968
|
+
selectInput(input);
|
|
751
969
|
} else if (user) prevInput = input.value = "";
|
|
752
970
|
}
|
|
753
971
|
|
|
754
972
|
function focusInput() {
|
|
755
|
-
if (
|
|
973
|
+
if (options.readOnly != "nocursor") input.focus();
|
|
756
974
|
}
|
|
757
975
|
|
|
758
976
|
function scrollEditorIntoView() {
|
|
@@ -761,55 +979,67 @@ var CodeMirror = (function() {
|
|
|
761
979
|
// IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
|
|
762
980
|
if (ie && rect.top == rect.bottom) return;
|
|
763
981
|
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
|
|
764
|
-
if (rect.top < 0 || rect.bottom > winH)
|
|
982
|
+
if (rect.top < 0 || rect.bottom > winH) scrollCursorIntoView();
|
|
765
983
|
}
|
|
766
984
|
function scrollCursorIntoView() {
|
|
985
|
+
var coords = calculateCursorCoords();
|
|
986
|
+
return scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
|
|
987
|
+
}
|
|
988
|
+
function calculateCursorCoords() {
|
|
767
989
|
var cursor = localCoords(sel.inverted ? sel.from : sel.to);
|
|
768
990
|
var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;
|
|
769
|
-
return
|
|
991
|
+
return {x: x, y: cursor.y, yBot: cursor.yBot};
|
|
770
992
|
}
|
|
771
993
|
function scrollIntoView(x1, y1, x2, y2) {
|
|
772
|
-
var
|
|
994
|
+
var scrollPos = calculateScrollPos(x1, y1, x2, y2), scrolled = false;
|
|
995
|
+
if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft; scrolled = true;}
|
|
996
|
+
if (scrollPos.scrollTop != null) {scrollbar.scrollTop = scrollPos.scrollTop; scrolled = true;}
|
|
997
|
+
if (scrolled && options.onScroll) options.onScroll(instance);
|
|
998
|
+
}
|
|
999
|
+
function calculateScrollPos(x1, y1, x2, y2) {
|
|
1000
|
+
var pl = paddingLeft(), pt = paddingTop();
|
|
773
1001
|
y1 += pt; y2 += pt; x1 += pl; x2 += pl;
|
|
774
|
-
var screen = scroller.clientHeight, screentop =
|
|
775
|
-
|
|
776
|
-
|
|
1002
|
+
var screen = scroller.clientHeight, screentop = scrollbar.scrollTop, result = {};
|
|
1003
|
+
var atTop = y1 < paddingTop() + 10;
|
|
1004
|
+
if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
|
|
1005
|
+
else if (y2 > screentop + screen) result.scrollTop = y2 - screen;
|
|
777
1006
|
|
|
778
1007
|
var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
|
|
779
1008
|
var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
1009
|
+
var atLeft = x1 < gutterw + pl + 10;
|
|
1010
|
+
if (x1 < screenleft + gutterw || atLeft) {
|
|
1011
|
+
if (atLeft) x1 = 0;
|
|
1012
|
+
result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
|
|
1013
|
+
} else if (x2 > screenw + screenleft - 3) {
|
|
1014
|
+
result.scrollLeft = x2 + 10 - screenw;
|
|
784
1015
|
}
|
|
785
|
-
else if (x2 > screenw + screenleft - 3) {
|
|
786
|
-
scroller.scrollLeft = x2 + 10 - screenw;
|
|
787
|
-
scrolled = true;
|
|
788
|
-
if (x2 > code.clientWidth) result = false;
|
|
789
|
-
}
|
|
790
|
-
if (scrolled && options.onScroll) options.onScroll(instance);
|
|
791
1016
|
return result;
|
|
792
1017
|
}
|
|
793
1018
|
|
|
794
|
-
function visibleLines() {
|
|
795
|
-
var lh = textHeight(), top =
|
|
796
|
-
var
|
|
797
|
-
var
|
|
798
|
-
return {from: lineAtHeight(doc,
|
|
799
|
-
to: lineAtHeight(doc,
|
|
1019
|
+
function visibleLines(scrollTop) {
|
|
1020
|
+
var lh = textHeight(), top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop();
|
|
1021
|
+
var fromHeight = Math.max(0, Math.floor(top / lh));
|
|
1022
|
+
var toHeight = Math.ceil((top + scroller.clientHeight) / lh);
|
|
1023
|
+
return {from: lineAtHeight(doc, fromHeight),
|
|
1024
|
+
to: lineAtHeight(doc, toHeight)};
|
|
800
1025
|
}
|
|
801
1026
|
// Uses a set of changes plus the current scroll position to
|
|
802
1027
|
// determine which DOM updates have to be made, and makes the
|
|
803
1028
|
// updates.
|
|
804
|
-
function updateDisplay(changes, suppressCallback) {
|
|
1029
|
+
function updateDisplay(changes, suppressCallback, scrollTop) {
|
|
805
1030
|
if (!scroller.clientWidth) {
|
|
806
1031
|
showingFrom = showingTo = displayOffset = 0;
|
|
807
1032
|
return;
|
|
808
1033
|
}
|
|
809
1034
|
// Compute the new visible window
|
|
810
|
-
|
|
1035
|
+
// If scrollTop is specified, use that to determine which lines
|
|
1036
|
+
// to render instead of the current scrollbar position.
|
|
1037
|
+
var visible = visibleLines(scrollTop);
|
|
811
1038
|
// Bail out if the visible area is already rendered and nothing changed.
|
|
812
|
-
if (changes !== true && changes.length == 0 && visible.from
|
|
1039
|
+
if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) {
|
|
1040
|
+
updateVerticalScroll(scrollTop);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
813
1043
|
var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);
|
|
814
1044
|
if (showingFrom < from && from - showingFrom < 20) from = showingFrom;
|
|
815
1045
|
if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);
|
|
@@ -827,24 +1057,23 @@ var CodeMirror = (function() {
|
|
|
827
1057
|
if (range.from >= range.to) intact.splice(i--, 1);
|
|
828
1058
|
else intactLines += range.to - range.from;
|
|
829
1059
|
}
|
|
830
|
-
if (intactLines == to - from)
|
|
1060
|
+
if (intactLines == to - from && from == showingFrom && to == showingTo) {
|
|
1061
|
+
updateVerticalScroll(scrollTop);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
831
1064
|
intact.sort(function(a, b) {return a.domStart - b.domStart;});
|
|
832
1065
|
|
|
833
1066
|
var th = textHeight(), gutterDisplay = gutter.style.display;
|
|
834
|
-
lineDiv.style.display =
|
|
1067
|
+
lineDiv.style.display = "none";
|
|
835
1068
|
patchDisplay(from, to, intact);
|
|
836
|
-
lineDiv.style.display = "";
|
|
1069
|
+
lineDiv.style.display = gutter.style.display = "";
|
|
837
1070
|
|
|
838
|
-
// Position the mover div to align with the lines it's supposed
|
|
839
|
-
// to be showing (which will cover the visible display)
|
|
840
1071
|
var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;
|
|
841
1072
|
// This is just a bogus formula that detects when the editor is
|
|
842
1073
|
// resized or the font size changes.
|
|
843
1074
|
if (different) lastSizeC = scroller.clientHeight + th;
|
|
844
1075
|
showingFrom = from; showingTo = to;
|
|
845
1076
|
displayOffset = heightAtLine(doc, from);
|
|
846
|
-
mover.style.top = (displayOffset * th) + "px";
|
|
847
|
-
code.style.height = (doc.height * th + 2 * paddingTop()) + "px";
|
|
848
1077
|
|
|
849
1078
|
// Since this is all rather error prone, it is honoured with the
|
|
850
1079
|
// only assertion in the whole file.
|
|
@@ -852,30 +1081,38 @@ var CodeMirror = (function() {
|
|
|
852
1081
|
throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) +
|
|
853
1082
|
" nodes=" + lineDiv.childNodes.length);
|
|
854
1083
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
var curNode = lineDiv.firstChild;
|
|
1084
|
+
function checkHeights() {
|
|
1085
|
+
var curNode = lineDiv.firstChild, heightChanged = false;
|
|
858
1086
|
doc.iter(showingFrom, showingTo, function(line) {
|
|
859
1087
|
if (!line.hidden) {
|
|
860
1088
|
var height = Math.round(curNode.offsetHeight / th) || 1;
|
|
861
|
-
if (line.height != height) {
|
|
1089
|
+
if (line.height != height) {
|
|
1090
|
+
updateLineHeight(line, height);
|
|
1091
|
+
gutterDirty = heightChanged = true;
|
|
1092
|
+
}
|
|
862
1093
|
}
|
|
863
1094
|
curNode = curNode.nextSibling;
|
|
864
1095
|
});
|
|
865
|
-
|
|
866
|
-
if (maxWidth == null) maxWidth = stringWidth(maxLine);
|
|
867
|
-
if (maxWidth > scroller.clientWidth) {
|
|
868
|
-
lineSpace.style.width = maxWidth + "px";
|
|
869
|
-
// Needed to prevent odd wrapping/hiding of widgets placed in here.
|
|
870
|
-
code.style.width = "";
|
|
871
|
-
code.style.width = scroller.scrollWidth + "px";
|
|
872
|
-
} else {
|
|
873
|
-
lineSpace.style.width = code.style.width = "";
|
|
874
|
-
}
|
|
1096
|
+
return heightChanged;
|
|
875
1097
|
}
|
|
1098
|
+
|
|
1099
|
+
if (options.lineWrapping) {
|
|
1100
|
+
// Guess whether we're going to need the scrollbar, so that we don't end up changing the linewrapping
|
|
1101
|
+
// after the scrollbar appears (during updateVerticalScroll()). Only do this if the scrollbar is
|
|
1102
|
+
// appearing (if it's disappearing, we don't have to worry about the scroll position, and there are
|
|
1103
|
+
// issues on IE7 if we turn it off too early).
|
|
1104
|
+
var virtualHeight = Math.floor(doc.height * th + 2 * paddingTop()), scrollbarHeight = scroller.clientHeight;
|
|
1105
|
+
if (virtualHeight > scrollbarHeight) scrollbar.style.display = "block";
|
|
1106
|
+
checkHeights();
|
|
1107
|
+
}
|
|
1108
|
+
|
|
876
1109
|
gutter.style.display = gutterDisplay;
|
|
877
|
-
if (different || gutterDirty)
|
|
878
|
-
|
|
1110
|
+
if (different || gutterDirty) {
|
|
1111
|
+
// If the gutter grew in size, re-check heights. If those changed, re-draw gutter.
|
|
1112
|
+
updateGutter() && options.lineWrapping && checkHeights() && updateGutter();
|
|
1113
|
+
}
|
|
1114
|
+
updateSelection();
|
|
1115
|
+
updateVerticalScroll(scrollTop);
|
|
879
1116
|
if (!suppressCallback && options.onUpdate) options.onUpdate(instance);
|
|
880
1117
|
return true;
|
|
881
1118
|
}
|
|
@@ -922,21 +1159,20 @@ var CodeMirror = (function() {
|
|
|
922
1159
|
}
|
|
923
1160
|
// This pass fills in the lines that actually changed.
|
|
924
1161
|
var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
|
|
925
|
-
var
|
|
926
|
-
var scratch = targetDocument.createElement("div"), newElt;
|
|
1162
|
+
var scratch = document.createElement("div");
|
|
927
1163
|
doc.iter(from, to, function(line) {
|
|
928
|
-
var ch1 = null, ch2 = null;
|
|
929
|
-
if (inSel) {
|
|
930
|
-
ch1 = 0;
|
|
931
|
-
if (sto == j) {inSel = false; ch2 = sel.to.ch;}
|
|
932
|
-
} else if (sfrom == j) {
|
|
933
|
-
if (sto == j) {ch1 = sel.from.ch; ch2 = sel.to.ch;}
|
|
934
|
-
else {inSel = true; ch1 = sel.from.ch;}
|
|
935
|
-
}
|
|
936
1164
|
if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
|
|
937
1165
|
if (!nextIntact || nextIntact.from > j) {
|
|
938
|
-
if (line.hidden) scratch.innerHTML = "<pre></pre>";
|
|
939
|
-
else
|
|
1166
|
+
if (line.hidden) var html = scratch.innerHTML = "<pre></pre>";
|
|
1167
|
+
else {
|
|
1168
|
+
var html = '<pre' + (line.className ? ' class="' + line.className + '"' : '') + '>'
|
|
1169
|
+
+ line.getHTML(makeTab) + '</pre>';
|
|
1170
|
+
// Kludge to make sure the styled element lies behind the selection (by z-index)
|
|
1171
|
+
if (line.bgClassName)
|
|
1172
|
+
html = '<div style="position: relative"><pre class="' + line.bgClassName +
|
|
1173
|
+
'" style="position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2"> </pre>' + html + "</div>";
|
|
1174
|
+
}
|
|
1175
|
+
scratch.innerHTML = html;
|
|
940
1176
|
lineDiv.insertBefore(scratch.firstChild, curNode);
|
|
941
1177
|
} else {
|
|
942
1178
|
curNode = curNode.nextSibling;
|
|
@@ -949,7 +1185,7 @@ var CodeMirror = (function() {
|
|
|
949
1185
|
if (!options.gutter && !options.lineNumbers) return;
|
|
950
1186
|
var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
|
|
951
1187
|
gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
|
|
952
|
-
var html = [], i = showingFrom;
|
|
1188
|
+
var html = [], i = showingFrom, normalNode;
|
|
953
1189
|
doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
|
|
954
1190
|
if (line.hidden) {
|
|
955
1191
|
html.push("<pre></pre>");
|
|
@@ -963,30 +1199,62 @@ var CodeMirror = (function() {
|
|
|
963
1199
|
html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text);
|
|
964
1200
|
for (var j = 1; j < line.height; ++j) html.push("<br/> ");
|
|
965
1201
|
html.push("</pre>");
|
|
1202
|
+
if (!marker) normalNode = i;
|
|
966
1203
|
}
|
|
967
1204
|
++i;
|
|
968
1205
|
});
|
|
969
1206
|
gutter.style.display = "none";
|
|
970
1207
|
gutterText.innerHTML = html.join("");
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1208
|
+
// Make sure scrolling doesn't cause number gutter size to pop
|
|
1209
|
+
if (normalNode != null && options.lineNumbers) {
|
|
1210
|
+
var node = gutterText.childNodes[normalNode - showingFrom];
|
|
1211
|
+
var minwidth = String(doc.size).length, val = eltText(node.firstChild), pad = "";
|
|
1212
|
+
while (val.length + pad.length < minwidth) pad += "\u00a0";
|
|
1213
|
+
if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);
|
|
1214
|
+
}
|
|
974
1215
|
gutter.style.display = "";
|
|
1216
|
+
var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2;
|
|
975
1217
|
lineSpace.style.marginLeft = gutter.offsetWidth + "px";
|
|
976
1218
|
gutterDirty = false;
|
|
1219
|
+
return resized;
|
|
977
1220
|
}
|
|
978
|
-
function
|
|
979
|
-
var
|
|
980
|
-
var
|
|
1221
|
+
function updateSelection() {
|
|
1222
|
+
var collapsed = posEq(sel.from, sel.to);
|
|
1223
|
+
var fromPos = localCoords(sel.from, true);
|
|
1224
|
+
var toPos = collapsed ? fromPos : localCoords(sel.to, true);
|
|
1225
|
+
var headPos = sel.inverted ? fromPos : toPos, th = textHeight();
|
|
981
1226
|
var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);
|
|
982
|
-
inputDiv.style.top = (
|
|
983
|
-
inputDiv.style.left = (
|
|
984
|
-
if (
|
|
985
|
-
cursor.style.top =
|
|
986
|
-
cursor.style.left = (options.lineWrapping ? Math.min(
|
|
1227
|
+
inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + "px";
|
|
1228
|
+
inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + "px";
|
|
1229
|
+
if (collapsed) {
|
|
1230
|
+
cursor.style.top = headPos.y + "px";
|
|
1231
|
+
cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + "px";
|
|
987
1232
|
cursor.style.display = "";
|
|
1233
|
+
selectionDiv.style.display = "none";
|
|
1234
|
+
} else {
|
|
1235
|
+
var sameLine = fromPos.y == toPos.y, html = "";
|
|
1236
|
+
var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
|
|
1237
|
+
var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
|
|
1238
|
+
function add(left, top, right, height) {
|
|
1239
|
+
var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px"
|
|
1240
|
+
: "right: " + right + "px";
|
|
1241
|
+
html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
|
|
1242
|
+
'px; top: ' + top + 'px; ' + rstyle + '; height: ' + height + 'px"></div>';
|
|
1243
|
+
}
|
|
1244
|
+
if (sel.from.ch && fromPos.y >= 0) {
|
|
1245
|
+
var right = sameLine ? clientWidth - toPos.x : 0;
|
|
1246
|
+
add(fromPos.x, fromPos.y, right, th);
|
|
1247
|
+
}
|
|
1248
|
+
var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));
|
|
1249
|
+
var middleHeight = Math.min(toPos.y, clientHeight) - middleStart;
|
|
1250
|
+
if (middleHeight > 0.2 * th)
|
|
1251
|
+
add(0, middleStart, 0, middleHeight);
|
|
1252
|
+
if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)
|
|
1253
|
+
add(0, toPos.y, clientWidth - toPos.x, th);
|
|
1254
|
+
selectionDiv.innerHTML = html;
|
|
1255
|
+
cursor.style.display = "none";
|
|
1256
|
+
selectionDiv.style.display = "";
|
|
988
1257
|
}
|
|
989
|
-
else cursor.style.display = "none";
|
|
990
1258
|
}
|
|
991
1259
|
|
|
992
1260
|
function setShift(val) {
|
|
@@ -1012,37 +1280,32 @@ var CodeMirror = (function() {
|
|
|
1012
1280
|
if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}
|
|
1013
1281
|
|
|
1014
1282
|
// Skip over hidden lines.
|
|
1015
|
-
if (from.line != oldFrom)
|
|
1283
|
+
if (from.line != oldFrom) {
|
|
1284
|
+
var from1 = skipHidden(from, oldFrom, sel.from.ch);
|
|
1285
|
+
// If there is no non-hidden line left, force visibility on current line
|
|
1286
|
+
if (!from1) setLineHidden(from.line, false);
|
|
1287
|
+
else from = from1;
|
|
1288
|
+
}
|
|
1016
1289
|
if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);
|
|
1017
1290
|
|
|
1018
1291
|
if (posEq(from, to)) sel.inverted = false;
|
|
1019
1292
|
else if (posEq(from, sel.to)) sel.inverted = false;
|
|
1020
1293
|
else if (posEq(to, sel.from)) sel.inverted = true;
|
|
1021
1294
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
if (!posEq(from, sel.from)) {
|
|
1034
|
-
if (from.line < oldFrom)
|
|
1035
|
-
changes.push({from: from.line, to: Math.min(to.line, oldFrom) + 1});
|
|
1036
|
-
else
|
|
1037
|
-
changes.push({from: oldFrom, to: Math.min(oldTo, from.line) + 1});
|
|
1038
|
-
}
|
|
1039
|
-
if (!posEq(to, sel.to)) {
|
|
1040
|
-
if (to.line < oldTo)
|
|
1041
|
-
changes.push({from: Math.max(oldFrom, from.line), to: oldTo + 1});
|
|
1042
|
-
else
|
|
1043
|
-
changes.push({from: Math.max(from.line, oldTo), to: to.line + 1});
|
|
1295
|
+
if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {
|
|
1296
|
+
var head = sel.inverted ? from : to;
|
|
1297
|
+
if (head.line != sel.from.line && sel.from.line < doc.size) {
|
|
1298
|
+
var oldLine = getLine(sel.from.line);
|
|
1299
|
+
if (/^\s+$/.test(oldLine.text))
|
|
1300
|
+
setTimeout(operation(function() {
|
|
1301
|
+
if (oldLine.parent && /^\s+$/.test(oldLine.text)) {
|
|
1302
|
+
var no = lineNo(oldLine);
|
|
1303
|
+
replaceRange("", {line: no, ch: 0}, {line: no, ch: oldLine.text.length});
|
|
1304
|
+
}
|
|
1305
|
+
}, 10));
|
|
1044
1306
|
}
|
|
1045
1307
|
}
|
|
1308
|
+
|
|
1046
1309
|
sel.from = from; sel.to = to;
|
|
1047
1310
|
selectionChanged = true;
|
|
1048
1311
|
}
|
|
@@ -1053,13 +1316,14 @@ var CodeMirror = (function() {
|
|
|
1053
1316
|
var line = getLine(lNo);
|
|
1054
1317
|
if (!line.hidden) {
|
|
1055
1318
|
var ch = pos.ch;
|
|
1056
|
-
if (ch > oldCh || ch > line.text.length) ch = line.text.length;
|
|
1319
|
+
if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;
|
|
1057
1320
|
return {line: lNo, ch: ch};
|
|
1058
1321
|
}
|
|
1059
1322
|
lNo += dir;
|
|
1060
1323
|
}
|
|
1061
1324
|
}
|
|
1062
1325
|
var line = getLine(pos.line);
|
|
1326
|
+
var toEnd = pos.ch == line.text.length && pos.ch != oldCh;
|
|
1063
1327
|
if (!line.hidden) return pos;
|
|
1064
1328
|
if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
|
|
1065
1329
|
else return getNonHidden(-1) || getNonHidden(1);
|
|
@@ -1123,9 +1387,10 @@ var CodeMirror = (function() {
|
|
|
1123
1387
|
function moveV(dir, unit) {
|
|
1124
1388
|
var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);
|
|
1125
1389
|
if (goalColumn != null) pos.x = goalColumn;
|
|
1126
|
-
if (unit == "page") dist = scroller.clientHeight;
|
|
1390
|
+
if (unit == "page") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
|
|
1127
1391
|
else if (unit == "line") dist = textHeight();
|
|
1128
1392
|
var target = coordsChar(pos.x, pos.y + dist * dir + 2);
|
|
1393
|
+
if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y;
|
|
1129
1394
|
setCursor(target.line, target.ch, true);
|
|
1130
1395
|
goalColumn = pos.x;
|
|
1131
1396
|
}
|
|
@@ -1138,7 +1403,7 @@ var CodeMirror = (function() {
|
|
|
1138
1403
|
setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});
|
|
1139
1404
|
}
|
|
1140
1405
|
function selectLine(line) {
|
|
1141
|
-
setSelectionUser({line: line, ch: 0}, {line: line, ch:
|
|
1406
|
+
setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));
|
|
1142
1407
|
}
|
|
1143
1408
|
function indentSelected(mode) {
|
|
1144
1409
|
if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);
|
|
@@ -1155,11 +1420,14 @@ var CodeMirror = (function() {
|
|
|
1155
1420
|
|
|
1156
1421
|
var line = getLine(n), curSpace = line.indentation(options.tabSize),
|
|
1157
1422
|
curSpaceString = line.text.match(/^\s*/)[0], indentation;
|
|
1423
|
+
if (how == "smart") {
|
|
1424
|
+
indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
|
|
1425
|
+
if (indentation == Pass) how = "prev";
|
|
1426
|
+
}
|
|
1158
1427
|
if (how == "prev") {
|
|
1159
1428
|
if (n) indentation = getLine(n-1).indentation(options.tabSize);
|
|
1160
1429
|
else indentation = 0;
|
|
1161
1430
|
}
|
|
1162
|
-
else if (how == "smart") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);
|
|
1163
1431
|
else if (how == "add") indentation = curSpace + options.indentUnit;
|
|
1164
1432
|
else if (how == "subtract") indentation = curSpace - options.indentUnit;
|
|
1165
1433
|
indentation = Math.max(0, indentation);
|
|
@@ -1168,8 +1436,7 @@ var CodeMirror = (function() {
|
|
|
1168
1436
|
if (!diff) {
|
|
1169
1437
|
if (sel.from.line != n && sel.to.line != n) return;
|
|
1170
1438
|
var indentString = curSpaceString;
|
|
1171
|
-
}
|
|
1172
|
-
else {
|
|
1439
|
+
} else {
|
|
1173
1440
|
var indentString = "", pos = 0;
|
|
1174
1441
|
if (options.indentWithTabs)
|
|
1175
1442
|
for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
|
|
@@ -1201,9 +1468,10 @@ var CodeMirror = (function() {
|
|
|
1201
1468
|
if (guess != 1) updateLineHeight(line, guess);
|
|
1202
1469
|
});
|
|
1203
1470
|
lineSpace.style.width = code.style.width = "";
|
|
1471
|
+
widthForcer.style.left = "";
|
|
1204
1472
|
} else {
|
|
1205
1473
|
wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
|
|
1206
|
-
|
|
1474
|
+
maxLine = ""; maxLineChanged = true;
|
|
1207
1475
|
doc.iter(0, doc.size, function(line) {
|
|
1208
1476
|
if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
|
|
1209
1477
|
if (line.text.length > maxLine.length) maxLine = line.text;
|
|
@@ -1211,18 +1479,21 @@ var CodeMirror = (function() {
|
|
|
1211
1479
|
}
|
|
1212
1480
|
changes.push({from: 0, to: doc.size});
|
|
1213
1481
|
}
|
|
1214
|
-
function
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
tabText = computeTabText();
|
|
1220
|
-
updateDisplay(true);
|
|
1482
|
+
function makeTab(col) {
|
|
1483
|
+
var w = options.tabSize - col % options.tabSize, cached = tabCache[w];
|
|
1484
|
+
if (cached) return cached;
|
|
1485
|
+
for (var str = '<span class="cm-tab">', i = 0; i < w; ++i) str += " ";
|
|
1486
|
+
return (tabCache[w] = {html: str + "</span>", width: w});
|
|
1221
1487
|
}
|
|
1222
1488
|
function themeChanged() {
|
|
1223
|
-
scroller.className = scroller.className.replace(/\s*cm-s-\
|
|
1489
|
+
scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
|
|
1224
1490
|
options.theme.replace(/(^|\s)\s*/g, " cm-s-");
|
|
1225
1491
|
}
|
|
1492
|
+
function keyMapChanged() {
|
|
1493
|
+
var style = keyMap[options.keyMap].style;
|
|
1494
|
+
wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
|
|
1495
|
+
(style ? " cm-keymap-" + style : "");
|
|
1496
|
+
}
|
|
1226
1497
|
|
|
1227
1498
|
function TextMarker() { this.set = []; }
|
|
1228
1499
|
TextMarker.prototype.clear = operation(function() {
|
|
@@ -1233,7 +1504,7 @@ var CodeMirror = (function() {
|
|
|
1233
1504
|
var lineN = lineNo(line);
|
|
1234
1505
|
min = Math.min(min, lineN); max = Math.max(max, lineN);
|
|
1235
1506
|
for (var j = 0; j < mk.length; ++j)
|
|
1236
|
-
if (mk[j].
|
|
1507
|
+
if (mk[j].marker == this) mk.splice(j--, 1);
|
|
1237
1508
|
}
|
|
1238
1509
|
if (min != Infinity)
|
|
1239
1510
|
changes.push({from: min, to: max + 1});
|
|
@@ -1244,7 +1515,7 @@ var CodeMirror = (function() {
|
|
|
1244
1515
|
var line = this.set[i], mk = line.marked;
|
|
1245
1516
|
for (var j = 0; j < mk.length; ++j) {
|
|
1246
1517
|
var mark = mk[j];
|
|
1247
|
-
if (mark.
|
|
1518
|
+
if (mark.marker == this) {
|
|
1248
1519
|
if (mark.from != null || mark.to != null) {
|
|
1249
1520
|
var found = lineNo(line);
|
|
1250
1521
|
if (found != null) {
|
|
@@ -1261,8 +1532,9 @@ var CodeMirror = (function() {
|
|
|
1261
1532
|
function markText(from, to, className) {
|
|
1262
1533
|
from = clipPos(from); to = clipPos(to);
|
|
1263
1534
|
var tm = new TextMarker();
|
|
1535
|
+
if (!posLess(from, to)) return tm;
|
|
1264
1536
|
function add(line, from, to, className) {
|
|
1265
|
-
getLine(line).addMark(new MarkedText(from, to, className, tm
|
|
1537
|
+
getLine(line).addMark(new MarkedText(from, to, className, tm));
|
|
1266
1538
|
}
|
|
1267
1539
|
if (from.line == to.line) add(from.line, from.ch, to.ch, className);
|
|
1268
1540
|
else {
|
|
@@ -1282,6 +1554,19 @@ var CodeMirror = (function() {
|
|
|
1282
1554
|
return bm;
|
|
1283
1555
|
}
|
|
1284
1556
|
|
|
1557
|
+
function findMarksAt(pos) {
|
|
1558
|
+
pos = clipPos(pos);
|
|
1559
|
+
var markers = [], marked = getLine(pos.line).marked;
|
|
1560
|
+
if (!marked) return markers;
|
|
1561
|
+
for (var i = 0, e = marked.length; i < e; ++i) {
|
|
1562
|
+
var m = marked[i];
|
|
1563
|
+
if ((m.from == null || m.from <= pos.ch) &&
|
|
1564
|
+
(m.to == null || m.to >= pos.ch))
|
|
1565
|
+
markers.push(m.marker || m);
|
|
1566
|
+
}
|
|
1567
|
+
return markers;
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1285
1570
|
function addGutterMarker(line, text, className) {
|
|
1286
1571
|
if (typeof line == "number") line = getLine(clipLine(line));
|
|
1287
1572
|
line.gutterMarker = {text: text, style: className};
|
|
@@ -1303,10 +1588,11 @@ var CodeMirror = (function() {
|
|
|
1303
1588
|
else return null;
|
|
1304
1589
|
return line;
|
|
1305
1590
|
}
|
|
1306
|
-
function setLineClass(handle, className) {
|
|
1591
|
+
function setLineClass(handle, className, bgClassName) {
|
|
1307
1592
|
return changeLine(handle, function(line) {
|
|
1308
|
-
if (line.className != className) {
|
|
1593
|
+
if (line.className != className || line.bgClassName != bgClassName) {
|
|
1309
1594
|
line.className = className;
|
|
1595
|
+
line.bgClassName = bgClassName;
|
|
1310
1596
|
return true;
|
|
1311
1597
|
}
|
|
1312
1598
|
});
|
|
@@ -1315,10 +1601,23 @@ var CodeMirror = (function() {
|
|
|
1315
1601
|
return changeLine(handle, function(line, no) {
|
|
1316
1602
|
if (line.hidden != hidden) {
|
|
1317
1603
|
line.hidden = hidden;
|
|
1604
|
+
if (!options.lineWrapping) {
|
|
1605
|
+
var l = line.text;
|
|
1606
|
+
if (hidden && l.length == maxLine.length) {
|
|
1607
|
+
updateMaxLine = true;
|
|
1608
|
+
} else if (!hidden && l.length > maxLine.length) {
|
|
1609
|
+
maxLine = l; maxWidth = null; updateMaxLine = false;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1318
1612
|
updateLineHeight(line, hidden ? 0 : 1);
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1613
|
+
var fline = sel.from.line, tline = sel.to.line;
|
|
1614
|
+
if (hidden && (fline == no || tline == no)) {
|
|
1615
|
+
var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;
|
|
1616
|
+
var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;
|
|
1617
|
+
// Can't hide the last visible line, we'd have no place to put the cursor
|
|
1618
|
+
if (!to) return;
|
|
1619
|
+
setSelection(from, to);
|
|
1620
|
+
}
|
|
1322
1621
|
return (gutterDirty = true);
|
|
1323
1622
|
}
|
|
1324
1623
|
});
|
|
@@ -1330,14 +1629,13 @@ var CodeMirror = (function() {
|
|
|
1330
1629
|
var n = line;
|
|
1331
1630
|
line = getLine(line);
|
|
1332
1631
|
if (!line) return null;
|
|
1333
|
-
}
|
|
1334
|
-
else {
|
|
1632
|
+
} else {
|
|
1335
1633
|
var n = lineNo(line);
|
|
1336
1634
|
if (n == null) return null;
|
|
1337
1635
|
}
|
|
1338
1636
|
var marker = line.gutterMarker;
|
|
1339
1637
|
return {line: n, handle: line, text: line.text, markerText: marker && marker.text,
|
|
1340
|
-
markerClass: marker && marker.style, lineClass: line.className};
|
|
1638
|
+
markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};
|
|
1341
1639
|
}
|
|
1342
1640
|
|
|
1343
1641
|
function stringWidth(str) {
|
|
@@ -1351,8 +1649,7 @@ var CodeMirror = (function() {
|
|
|
1351
1649
|
if (x <= 0) return 0;
|
|
1352
1650
|
var lineObj = getLine(line), text = lineObj.text;
|
|
1353
1651
|
function getX(len) {
|
|
1354
|
-
|
|
1355
|
-
return measure.firstChild.firstChild.offsetWidth;
|
|
1652
|
+
return measureLine(lineObj, len).left;
|
|
1356
1653
|
}
|
|
1357
1654
|
var from = 0, fromX = 0, to = text.length, toX;
|
|
1358
1655
|
// Guess a suitable upper bound for our search.
|
|
@@ -1375,21 +1672,16 @@ var CodeMirror = (function() {
|
|
|
1375
1672
|
}
|
|
1376
1673
|
}
|
|
1377
1674
|
|
|
1378
|
-
var tempId = Math.floor(Math.random() * 0xffffff).toString(16);
|
|
1675
|
+
var tempId = "CodeMirror-temp-" + Math.floor(Math.random() * 0xffffff).toString(16);
|
|
1379
1676
|
function measureLine(line, ch) {
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
}
|
|
1386
|
-
measure.innerHTML = "<pre>" + line.getHTML(null, null, false, tabText, ch) +
|
|
1387
|
-
'<span id="CodeMirror-temp-' + tempId + '">' + htmlEscape(line.text.charAt(ch) || " ") + "</span>" +
|
|
1388
|
-
extra + "</pre>";
|
|
1389
|
-
var elt = document.getElementById("CodeMirror-temp-" + tempId);
|
|
1677
|
+
if (ch == 0) return {top: 0, left: 0};
|
|
1678
|
+
var wbr = options.lineWrapping && ch < line.text.length &&
|
|
1679
|
+
spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
|
|
1680
|
+
measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch, tempId, wbr) + "</pre>";
|
|
1681
|
+
var elt = document.getElementById(tempId);
|
|
1390
1682
|
var top = elt.offsetTop, left = elt.offsetLeft;
|
|
1391
1683
|
// Older IEs report zero offsets for spans directly after a wrap
|
|
1392
|
-
if (ie &&
|
|
1684
|
+
if (ie && top == 0 && left == 0) {
|
|
1393
1685
|
var backup = document.createElement("span");
|
|
1394
1686
|
backup.innerHTML = "x";
|
|
1395
1687
|
elt.parentNode.insertBefore(backup, elt.nextSibling);
|
|
@@ -1486,8 +1778,8 @@ var CodeMirror = (function() {
|
|
|
1486
1778
|
return coordsChar(x - offL.left, y - offL.top);
|
|
1487
1779
|
}
|
|
1488
1780
|
function onContextMenu(e) {
|
|
1489
|
-
var pos = posFromMouse(e);
|
|
1490
|
-
if (!pos ||
|
|
1781
|
+
var pos = posFromMouse(e), scrollPos = scrollbar.scrollTop;
|
|
1782
|
+
if (!pos || opera) return; // Opera is difficult.
|
|
1491
1783
|
if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
|
|
1492
1784
|
operation(setCursor)(pos.line, pos.ch);
|
|
1493
1785
|
|
|
@@ -1499,12 +1791,13 @@ var CodeMirror = (function() {
|
|
|
1499
1791
|
leaveInputAlone = true;
|
|
1500
1792
|
var val = input.value = getSelection();
|
|
1501
1793
|
focusInput();
|
|
1502
|
-
input
|
|
1794
|
+
selectInput(input);
|
|
1503
1795
|
function rehide() {
|
|
1504
1796
|
var newVal = splitLines(input.value).join("\n");
|
|
1505
|
-
if (newVal != val) operation(replaceSelection)(newVal, "end");
|
|
1797
|
+
if (newVal != val && !options.readOnly) operation(replaceSelection)(newVal, "end");
|
|
1506
1798
|
inputDiv.style.position = "relative";
|
|
1507
1799
|
input.style.cssText = oldCSS;
|
|
1800
|
+
if (ie_lt9) scrollbar.scrollTop = scrollPos;
|
|
1508
1801
|
leaveInputAlone = false;
|
|
1509
1802
|
resetInput(true);
|
|
1510
1803
|
slowPoll();
|
|
@@ -1516,8 +1809,7 @@ var CodeMirror = (function() {
|
|
|
1516
1809
|
mouseup();
|
|
1517
1810
|
setTimeout(rehide, 20);
|
|
1518
1811
|
}, true);
|
|
1519
|
-
}
|
|
1520
|
-
else {
|
|
1812
|
+
} else {
|
|
1521
1813
|
setTimeout(rehide, 50);
|
|
1522
1814
|
}
|
|
1523
1815
|
}
|
|
@@ -1547,7 +1839,7 @@ var CodeMirror = (function() {
|
|
|
1547
1839
|
var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
|
|
1548
1840
|
for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
|
|
1549
1841
|
var text = st[i];
|
|
1550
|
-
if (st[i+1] !=
|
|
1842
|
+
if (st[i+1] != style) {pos += d * text.length; continue;}
|
|
1551
1843
|
for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
|
|
1552
1844
|
if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
|
|
1553
1845
|
var match = matching[cur];
|
|
@@ -1634,13 +1926,17 @@ var CodeMirror = (function() {
|
|
|
1634
1926
|
var changed = line.highlight(mode, state, options.tabSize);
|
|
1635
1927
|
if (changed) realChange = true;
|
|
1636
1928
|
line.stateAfter = copyState(mode, state);
|
|
1929
|
+
var done = null;
|
|
1637
1930
|
if (compare) {
|
|
1638
|
-
|
|
1639
|
-
|
|
1931
|
+
var same = hadState && compare(hadState, state);
|
|
1932
|
+
if (same != Pass) done = !!same;
|
|
1933
|
+
}
|
|
1934
|
+
if (done == null) {
|
|
1640
1935
|
if (changed !== false || !hadState) unchanged = 0;
|
|
1641
1936
|
else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
|
|
1642
|
-
|
|
1937
|
+
done = true;
|
|
1643
1938
|
}
|
|
1939
|
+
if (done) return true;
|
|
1644
1940
|
++i;
|
|
1645
1941
|
});
|
|
1646
1942
|
if (bail) return;
|
|
@@ -1663,14 +1959,22 @@ var CodeMirror = (function() {
|
|
|
1663
1959
|
changes = []; selectionChanged = false; callbacks = [];
|
|
1664
1960
|
}
|
|
1665
1961
|
function endOperation() {
|
|
1666
|
-
|
|
1667
|
-
if (
|
|
1668
|
-
|
|
1962
|
+
if (updateMaxLine) computeMaxLength();
|
|
1963
|
+
if (maxLineChanged && !options.lineWrapping) {
|
|
1964
|
+
widthForcer.style.left = stringWidth(maxLine) + "px";
|
|
1965
|
+
maxLineChanged = false;
|
|
1966
|
+
}
|
|
1967
|
+
var newScrollPos, updated;
|
|
1968
|
+
if (selectionChanged) {
|
|
1969
|
+
var coords = calculateCursorCoords();
|
|
1970
|
+
newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot);
|
|
1971
|
+
}
|
|
1972
|
+
if (changes.length) updated = updateDisplay(changes, true, (newScrollPos ? newScrollPos.scrollTop : null));
|
|
1669
1973
|
else {
|
|
1670
|
-
if (selectionChanged)
|
|
1974
|
+
if (selectionChanged) updateSelection();
|
|
1671
1975
|
if (gutterDirty) updateGutter();
|
|
1672
1976
|
}
|
|
1673
|
-
if (
|
|
1977
|
+
if (newScrollPos) scrollCursorIntoView();
|
|
1674
1978
|
if (selectionChanged) {scrollEditorIntoView(); restartBlink();}
|
|
1675
1979
|
|
|
1676
1980
|
if (focused && !leaveInputAlone &&
|
|
@@ -1682,11 +1986,11 @@ var CodeMirror = (function() {
|
|
|
1682
1986
|
if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
|
|
1683
1987
|
if (posEq(sel.from, sel.to)) matchBrackets(false);
|
|
1684
1988
|
}), 20);
|
|
1685
|
-
var
|
|
1686
|
-
if (
|
|
1989
|
+
var sc = selectionChanged, cbs = callbacks; // these can be reset by callbacks
|
|
1990
|
+
if (textChanged && options.onChange && instance)
|
|
1991
|
+
options.onChange(instance, textChanged);
|
|
1992
|
+
if (sc && options.onCursorActivity)
|
|
1687
1993
|
options.onCursorActivity(instance);
|
|
1688
|
-
if (tc && options.onChange && instance)
|
|
1689
|
-
options.onChange(instance, tc);
|
|
1690
1994
|
for (var i = 0; i < cbs.length; ++i) cbs[i](instance);
|
|
1691
1995
|
if (updated && options.onUpdate) options.onUpdate(instance);
|
|
1692
1996
|
}
|
|
@@ -1700,6 +2004,11 @@ var CodeMirror = (function() {
|
|
|
1700
2004
|
};
|
|
1701
2005
|
}
|
|
1702
2006
|
|
|
2007
|
+
function compoundChange(f) {
|
|
2008
|
+
history.startCompound();
|
|
2009
|
+
try { return f(); } finally { history.endCompound(); }
|
|
2010
|
+
}
|
|
2011
|
+
|
|
1703
2012
|
for (var ext in extensions)
|
|
1704
2013
|
if (extensions.propertyIsEnumerable(ext) &&
|
|
1705
2014
|
!instance.propertyIsEnumerable(ext))
|
|
@@ -1714,17 +2023,21 @@ var CodeMirror = (function() {
|
|
|
1714
2023
|
theme: "default",
|
|
1715
2024
|
indentUnit: 2,
|
|
1716
2025
|
indentWithTabs: false,
|
|
2026
|
+
smartIndent: true,
|
|
1717
2027
|
tabSize: 4,
|
|
1718
2028
|
keyMap: "default",
|
|
1719
2029
|
extraKeys: null,
|
|
1720
2030
|
electricChars: true,
|
|
2031
|
+
autoClearEmptyLines: false,
|
|
1721
2032
|
onKeyEvent: null,
|
|
2033
|
+
onDragEvent: null,
|
|
1722
2034
|
lineWrapping: false,
|
|
1723
2035
|
lineNumbers: false,
|
|
1724
2036
|
gutter: false,
|
|
1725
2037
|
fixedGutter: false,
|
|
1726
2038
|
firstLineNumber: 1,
|
|
1727
2039
|
readOnly: false,
|
|
2040
|
+
dragDrop: true,
|
|
1728
2041
|
onChange: null,
|
|
1729
2042
|
onCursorActivity: null,
|
|
1730
2043
|
onGutterClick: null,
|
|
@@ -1737,34 +2050,39 @@ var CodeMirror = (function() {
|
|
|
1737
2050
|
pollInterval: 100,
|
|
1738
2051
|
undoDepth: 40,
|
|
1739
2052
|
tabindex: null,
|
|
1740
|
-
|
|
2053
|
+
autofocus: null
|
|
1741
2054
|
};
|
|
1742
2055
|
|
|
1743
|
-
var
|
|
2056
|
+
var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
|
|
2057
|
+
var mac = ios || /Mac/.test(navigator.platform);
|
|
1744
2058
|
var win = /Win/.test(navigator.platform);
|
|
1745
2059
|
|
|
1746
2060
|
// Known modes, by name and by MIME
|
|
1747
|
-
var modes = {}, mimeModes = {};
|
|
2061
|
+
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
|
|
1748
2062
|
CodeMirror.defineMode = function(name, mode) {
|
|
1749
2063
|
if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
|
|
2064
|
+
if (arguments.length > 2) {
|
|
2065
|
+
mode.dependencies = [];
|
|
2066
|
+
for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
|
|
2067
|
+
}
|
|
1750
2068
|
modes[name] = mode;
|
|
1751
2069
|
};
|
|
1752
2070
|
CodeMirror.defineMIME = function(mime, spec) {
|
|
1753
2071
|
mimeModes[mime] = spec;
|
|
1754
2072
|
};
|
|
1755
|
-
CodeMirror.
|
|
2073
|
+
CodeMirror.resolveMode = function(spec) {
|
|
1756
2074
|
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
|
|
1757
2075
|
spec = mimeModes[spec];
|
|
1758
|
-
if (typeof spec == "string")
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
return mfactory(options,
|
|
2076
|
+
else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec))
|
|
2077
|
+
return CodeMirror.resolveMode("application/xml");
|
|
2078
|
+
if (typeof spec == "string") return {name: spec};
|
|
2079
|
+
else return spec || {name: "null"};
|
|
2080
|
+
};
|
|
2081
|
+
CodeMirror.getMode = function(options, spec) {
|
|
2082
|
+
var spec = CodeMirror.resolveMode(spec);
|
|
2083
|
+
var mfactory = modes[spec.name];
|
|
2084
|
+
if (!mfactory) return CodeMirror.getMode(options, "text/plain");
|
|
2085
|
+
return mfactory(options, spec);
|
|
1768
2086
|
};
|
|
1769
2087
|
CodeMirror.listModes = function() {
|
|
1770
2088
|
var list = [];
|
|
@@ -1821,6 +2139,10 @@ var CodeMirror = (function() {
|
|
|
1821
2139
|
indentMore: function(cm) {cm.indentSelection("add");},
|
|
1822
2140
|
indentLess: function(cm) {cm.indentSelection("subtract");},
|
|
1823
2141
|
insertTab: function(cm) {cm.replaceSelection("\t", "end");},
|
|
2142
|
+
defaultTab: function(cm) {
|
|
2143
|
+
if (cm.somethingSelected()) cm.indentSelection("add");
|
|
2144
|
+
else cm.replaceSelection("\t", "end");
|
|
2145
|
+
},
|
|
1824
2146
|
transposeChars: function(cm) {
|
|
1825
2147
|
var cur = cm.getCursor(), line = cm.getLine(cur.line);
|
|
1826
2148
|
if (cur.ch > 0 && cur.ch < line.length - 1)
|
|
@@ -1838,7 +2160,7 @@ var CodeMirror = (function() {
|
|
|
1838
2160
|
keyMap.basic = {
|
|
1839
2161
|
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
|
|
1840
2162
|
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
|
|
1841
|
-
"Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "
|
|
2163
|
+
"Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
|
|
1842
2164
|
"Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
|
|
1843
2165
|
};
|
|
1844
2166
|
// Note that the save and find-related commands aren't defined by
|
|
@@ -1849,6 +2171,7 @@ var CodeMirror = (function() {
|
|
|
1849
2171
|
"Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
|
|
1850
2172
|
"Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find",
|
|
1851
2173
|
"Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
|
|
2174
|
+
"Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
|
|
1852
2175
|
fallthrough: "basic"
|
|
1853
2176
|
};
|
|
1854
2177
|
keyMap.macDefault = {
|
|
@@ -1857,6 +2180,7 @@ var CodeMirror = (function() {
|
|
|
1857
2180
|
"Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft",
|
|
1858
2181
|
"Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find",
|
|
1859
2182
|
"Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
|
|
2183
|
+
"Cmd-[": "indentLess", "Cmd-]": "indentMore",
|
|
1860
2184
|
fallthrough: ["basic", "emacsy"]
|
|
1861
2185
|
};
|
|
1862
2186
|
keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
|
|
@@ -1867,23 +2191,33 @@ var CodeMirror = (function() {
|
|
|
1867
2191
|
"Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
|
|
1868
2192
|
};
|
|
1869
2193
|
|
|
1870
|
-
function
|
|
1871
|
-
|
|
2194
|
+
function getKeyMap(val) {
|
|
2195
|
+
if (typeof val == "string") return keyMap[val];
|
|
2196
|
+
else return val;
|
|
2197
|
+
}
|
|
2198
|
+
function lookupKey(name, extraMap, map, handle, stop) {
|
|
2199
|
+
function lookup(map) {
|
|
2200
|
+
map = getKeyMap(map);
|
|
1872
2201
|
var found = map[name];
|
|
1873
|
-
if (found != null) return
|
|
1874
|
-
if (
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
for (var i = 0, e = ft.length; i < e; ++i) {
|
|
1878
|
-
found = lookup(name, keyMap[ft[i]]);
|
|
1879
|
-
if (found != null) return found;
|
|
2202
|
+
if (found != null && handle(found)) return true;
|
|
2203
|
+
if (map.nofallthrough) {
|
|
2204
|
+
if (stop) stop();
|
|
2205
|
+
return true;
|
|
1880
2206
|
}
|
|
1881
|
-
|
|
2207
|
+
var fallthrough = map.fallthrough;
|
|
2208
|
+
if (fallthrough == null) return false;
|
|
2209
|
+
if (Object.prototype.toString.call(fallthrough) != "[object Array]")
|
|
2210
|
+
return lookup(fallthrough);
|
|
2211
|
+
for (var i = 0, e = fallthrough.length; i < e; ++i) {
|
|
2212
|
+
if (lookup(fallthrough[i])) return true;
|
|
2213
|
+
}
|
|
2214
|
+
return false;
|
|
1882
2215
|
}
|
|
1883
|
-
|
|
2216
|
+
if (extraMap && lookup(extraMap)) return true;
|
|
2217
|
+
return lookup(map);
|
|
1884
2218
|
}
|
|
1885
2219
|
function isModifierKey(event) {
|
|
1886
|
-
var name = keyNames[event
|
|
2220
|
+
var name = keyNames[e_prop(event, "keyCode")];
|
|
1887
2221
|
return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
|
|
1888
2222
|
}
|
|
1889
2223
|
|
|
@@ -1892,6 +2226,8 @@ var CodeMirror = (function() {
|
|
|
1892
2226
|
options.value = textarea.value;
|
|
1893
2227
|
if (!options.tabindex && textarea.tabindex)
|
|
1894
2228
|
options.tabindex = textarea.tabindex;
|
|
2229
|
+
if (options.autofocus == null && textarea.getAttribute("autofocus") != null)
|
|
2230
|
+
options.autofocus = true;
|
|
1895
2231
|
|
|
1896
2232
|
function save() {textarea.value = instance.getValue();}
|
|
1897
2233
|
if (textarea.form) {
|
|
@@ -1992,8 +2328,7 @@ var CodeMirror = (function() {
|
|
|
1992
2328
|
if (consume !== false) this.pos += pattern.length;
|
|
1993
2329
|
return true;
|
|
1994
2330
|
}
|
|
1995
|
-
}
|
|
1996
|
-
else {
|
|
2331
|
+
} else {
|
|
1997
2332
|
var match = this.string.slice(this.pos).match(pattern);
|
|
1998
2333
|
if (match && consume !== false) this.pos += match[0].length;
|
|
1999
2334
|
return match;
|
|
@@ -2003,34 +2338,34 @@ var CodeMirror = (function() {
|
|
|
2003
2338
|
};
|
|
2004
2339
|
CodeMirror.StringStream = StringStream;
|
|
2005
2340
|
|
|
2006
|
-
function MarkedText(from, to, className,
|
|
2007
|
-
this.from = from; this.to = to; this.style = className; this.
|
|
2341
|
+
function MarkedText(from, to, className, marker) {
|
|
2342
|
+
this.from = from; this.to = to; this.style = className; this.marker = marker;
|
|
2008
2343
|
}
|
|
2009
2344
|
MarkedText.prototype = {
|
|
2010
|
-
attach: function(line) { this.set.push(line); },
|
|
2345
|
+
attach: function(line) { this.marker.set.push(line); },
|
|
2011
2346
|
detach: function(line) {
|
|
2012
|
-
var ix = indexOf(this.set, line);
|
|
2013
|
-
if (ix > -1) this.set.splice(ix, 1);
|
|
2347
|
+
var ix = indexOf(this.marker.set, line);
|
|
2348
|
+
if (ix > -1) this.marker.set.splice(ix, 1);
|
|
2014
2349
|
},
|
|
2015
2350
|
split: function(pos, lenBefore) {
|
|
2016
2351
|
if (this.to <= pos && this.to != null) return null;
|
|
2017
2352
|
var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;
|
|
2018
2353
|
var to = this.to == null ? null : this.to - pos + lenBefore;
|
|
2019
|
-
return new MarkedText(from, to, this.style, this.
|
|
2354
|
+
return new MarkedText(from, to, this.style, this.marker);
|
|
2020
2355
|
},
|
|
2021
|
-
dup: function() { return new MarkedText(null, null, this.style, this.
|
|
2356
|
+
dup: function() { return new MarkedText(null, null, this.style, this.marker); },
|
|
2022
2357
|
clipTo: function(fromOpen, from, toOpen, to, diff) {
|
|
2023
|
-
if (this.from != null && this.from >= from)
|
|
2024
|
-
this.from = Math.max(to, this.from) + diff;
|
|
2025
|
-
if (this.to != null && this.to > from)
|
|
2026
|
-
this.to = to < this.to ? this.to + diff : from;
|
|
2027
2358
|
if (fromOpen && to > this.from && (to < this.to || this.to == null))
|
|
2028
2359
|
this.from = null;
|
|
2360
|
+
else if (this.from != null && this.from >= from)
|
|
2361
|
+
this.from = Math.max(to, this.from) + diff;
|
|
2029
2362
|
if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))
|
|
2030
2363
|
this.to = null;
|
|
2364
|
+
else if (this.to != null && this.to > from)
|
|
2365
|
+
this.to = to < this.to ? this.to + diff : from;
|
|
2031
2366
|
},
|
|
2032
2367
|
isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },
|
|
2033
|
-
sameSet: function(x) { return this.
|
|
2368
|
+
sameSet: function(x) { return this.marker == x.marker; }
|
|
2034
2369
|
};
|
|
2035
2370
|
|
|
2036
2371
|
function Bookmark(pos) {
|
|
@@ -2073,7 +2408,7 @@ var CodeMirror = (function() {
|
|
|
2073
2408
|
this.styles = styles || [text, null];
|
|
2074
2409
|
this.text = text;
|
|
2075
2410
|
this.height = 1;
|
|
2076
|
-
this.marked = this.gutterMarker = this.className = this.handlers = null;
|
|
2411
|
+
this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;
|
|
2077
2412
|
this.stateAfter = this.parent = this.hidden = null;
|
|
2078
2413
|
}
|
|
2079
2414
|
Line.inheritMarks = function(text, orig) {
|
|
@@ -2100,7 +2435,8 @@ var CodeMirror = (function() {
|
|
|
2100
2435
|
this.stateAfter = null;
|
|
2101
2436
|
if (mk) {
|
|
2102
2437
|
var diff = text.length - (to - from);
|
|
2103
|
-
for (var i = 0
|
|
2438
|
+
for (var i = 0; i < mk.length; ++i) {
|
|
2439
|
+
var mark = mk[i];
|
|
2104
2440
|
mark.clipTo(from == null, from || 0, to_ == null, to, diff);
|
|
2105
2441
|
if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}
|
|
2106
2442
|
}
|
|
@@ -2118,6 +2454,7 @@ var CodeMirror = (function() {
|
|
|
2118
2454
|
if (newmark) {
|
|
2119
2455
|
if (!taken.marked) taken.marked = [];
|
|
2120
2456
|
taken.marked.push(newmark); newmark.attach(taken);
|
|
2457
|
+
if (newmark == mark) mk.splice(i--, 1);
|
|
2121
2458
|
}
|
|
2122
2459
|
}
|
|
2123
2460
|
}
|
|
@@ -2227,73 +2564,116 @@ var CodeMirror = (function() {
|
|
|
2227
2564
|
indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
|
|
2228
2565
|
// Produces an HTML fragment for the line, taking selection,
|
|
2229
2566
|
// marking, and highlighting into account.
|
|
2230
|
-
getHTML: function(
|
|
2231
|
-
var html = [], first = true;
|
|
2232
|
-
|
|
2233
|
-
html.push(this.className ? '<pre class="' + this.className + '">': "<pre>");
|
|
2234
|
-
function span(text, style) {
|
|
2567
|
+
getHTML: function(makeTab, wrapAt, wrapId, wrapWBR) {
|
|
2568
|
+
var html = [], first = true, col = 0;
|
|
2569
|
+
function span_(text, style) {
|
|
2235
2570
|
if (!text) return;
|
|
2236
2571
|
// Work around a bug where, in some compat modes, IE ignores leading spaces
|
|
2237
2572
|
if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
|
|
2238
2573
|
first = false;
|
|
2239
|
-
if (
|
|
2240
|
-
|
|
2574
|
+
if (text.indexOf("\t") == -1) {
|
|
2575
|
+
col += text.length;
|
|
2576
|
+
var escaped = htmlEscape(text);
|
|
2577
|
+
} else {
|
|
2578
|
+
var escaped = "";
|
|
2579
|
+
for (var pos = 0;;) {
|
|
2580
|
+
var idx = text.indexOf("\t", pos);
|
|
2581
|
+
if (idx == -1) {
|
|
2582
|
+
escaped += htmlEscape(text.slice(pos));
|
|
2583
|
+
col += text.length - pos;
|
|
2584
|
+
break;
|
|
2585
|
+
} else {
|
|
2586
|
+
col += idx - pos;
|
|
2587
|
+
var tab = makeTab(col);
|
|
2588
|
+
escaped += htmlEscape(text.slice(pos, idx)) + tab.html;
|
|
2589
|
+
col += tab.width;
|
|
2590
|
+
pos = idx + 1;
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
if (style) html.push('<span class="', style, '">', escaped, "</span>");
|
|
2595
|
+
else html.push(escaped);
|
|
2596
|
+
}
|
|
2597
|
+
var span = span_;
|
|
2598
|
+
if (wrapAt != null) {
|
|
2599
|
+
var outPos = 0, open = "<span id=\"" + wrapId + "\">";
|
|
2600
|
+
span = function(text, style) {
|
|
2601
|
+
var l = text.length;
|
|
2602
|
+
if (wrapAt >= outPos && wrapAt < outPos + l) {
|
|
2603
|
+
if (wrapAt > outPos) {
|
|
2604
|
+
span_(text.slice(0, wrapAt - outPos), style);
|
|
2605
|
+
// See comment at the definition of spanAffectsWrapping
|
|
2606
|
+
if (wrapWBR) html.push("<wbr>");
|
|
2607
|
+
}
|
|
2608
|
+
html.push(open);
|
|
2609
|
+
var cut = wrapAt - outPos;
|
|
2610
|
+
span_(opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
|
|
2611
|
+
html.push("</span>");
|
|
2612
|
+
if (opera) span_(text.slice(cut + 1), style);
|
|
2613
|
+
wrapAt--;
|
|
2614
|
+
outPos += l;
|
|
2615
|
+
} else {
|
|
2616
|
+
outPos += l;
|
|
2617
|
+
span_(text, style);
|
|
2618
|
+
// Output empty wrapper when at end of line
|
|
2619
|
+
if (outPos == wrapAt && outPos == len) html.push(open + " </span>");
|
|
2620
|
+
// Stop outputting HTML when gone sufficiently far beyond measure
|
|
2621
|
+
else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2241
2624
|
}
|
|
2625
|
+
|
|
2242
2626
|
var st = this.styles, allText = this.text, marked = this.marked;
|
|
2243
|
-
if (sfrom == sto) sfrom = null;
|
|
2244
2627
|
var len = allText.length;
|
|
2245
|
-
|
|
2628
|
+
function styleToClass(style) {
|
|
2629
|
+
if (!style) return null;
|
|
2630
|
+
return "cm-" + style.replace(/ +/g, " cm-");
|
|
2631
|
+
}
|
|
2246
2632
|
|
|
2247
|
-
if (!allText &&
|
|
2248
|
-
span(" "
|
|
2249
|
-
else if (!marked
|
|
2633
|
+
if (!allText && wrapAt == null) {
|
|
2634
|
+
span(" ");
|
|
2635
|
+
} else if (!marked || !marked.length) {
|
|
2250
2636
|
for (var i = 0, ch = 0; ch < len; i+=2) {
|
|
2251
2637
|
var str = st[i], style = st[i+1], l = str.length;
|
|
2252
2638
|
if (ch + l > len) str = str.slice(0, len - ch);
|
|
2253
2639
|
ch += l;
|
|
2254
|
-
span(str, style
|
|
2640
|
+
span(str, styleToClass(style));
|
|
2255
2641
|
}
|
|
2256
|
-
else {
|
|
2642
|
+
} else {
|
|
2257
2643
|
var pos = 0, i = 0, text = "", style, sg = 0;
|
|
2258
|
-
var
|
|
2259
|
-
function
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2644
|
+
var nextChange = marked[0].from || 0, marks = [], markpos = 0;
|
|
2645
|
+
function advanceMarks() {
|
|
2646
|
+
var m;
|
|
2647
|
+
while (markpos < marked.length &&
|
|
2648
|
+
((m = marked[markpos]).from == pos || m.from == null)) {
|
|
2649
|
+
if (m.style != null) marks.push(m);
|
|
2650
|
+
++markpos;
|
|
2651
|
+
}
|
|
2652
|
+
nextChange = markpos < marked.length ? marked[markpos].from : Infinity;
|
|
2653
|
+
for (var i = 0; i < marks.length; ++i) {
|
|
2654
|
+
var to = marks[i].to || Infinity;
|
|
2655
|
+
if (to == pos) marks.splice(i--, 1);
|
|
2656
|
+
else nextChange = Math.min(to, nextChange);
|
|
2263
2657
|
}
|
|
2264
2658
|
}
|
|
2265
|
-
|
|
2659
|
+
var m = 0;
|
|
2266
2660
|
while (pos < len) {
|
|
2267
|
-
|
|
2268
|
-
var
|
|
2269
|
-
|
|
2270
|
-
if (
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
if (mark.from > pos) upto = Math.min(upto, mark.from);
|
|
2279
|
-
else {
|
|
2280
|
-
extraStyle += " " + mark.style;
|
|
2281
|
-
if (mark.to != null) upto = Math.min(upto, mark.to);
|
|
2661
|
+
if (nextChange == pos) advanceMarks();
|
|
2662
|
+
var upto = Math.min(len, nextChange);
|
|
2663
|
+
while (true) {
|
|
2664
|
+
if (text) {
|
|
2665
|
+
var end = pos + text.length;
|
|
2666
|
+
var appliedStyle = style;
|
|
2667
|
+
for (var j = 0; j < marks.length; ++j)
|
|
2668
|
+
appliedStyle = (appliedStyle ? appliedStyle + " " : "") + marks[j].style;
|
|
2669
|
+
span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
|
|
2670
|
+
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
|
|
2671
|
+
pos = end;
|
|
2282
2672
|
}
|
|
2283
|
-
|
|
2284
|
-
for (;;) {
|
|
2285
|
-
var end = pos + text.length;
|
|
2286
|
-
var appliedStyle = style;
|
|
2287
|
-
if (extraStyle) appliedStyle = style ? style + extraStyle : extraStyle;
|
|
2288
|
-
span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
|
|
2289
|
-
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
|
|
2290
|
-
pos = end;
|
|
2291
|
-
text = st[i++]; style = "cm-" + st[i++];
|
|
2673
|
+
text = st[i++]; style = styleToClass(st[i++]);
|
|
2292
2674
|
}
|
|
2293
2675
|
}
|
|
2294
|
-
if (sfrom != null && sto == null) span(" ", "CodeMirror-selected");
|
|
2295
2676
|
}
|
|
2296
|
-
if (includePre) html.push("</pre>");
|
|
2297
2677
|
return html.join("");
|
|
2298
2678
|
},
|
|
2299
2679
|
cleanUp: function() {
|
|
@@ -2309,8 +2689,7 @@ var CodeMirror = (function() {
|
|
|
2309
2689
|
if (state == 0) {
|
|
2310
2690
|
if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);
|
|
2311
2691
|
if (end >= from) state = 1;
|
|
2312
|
-
}
|
|
2313
|
-
else if (state == 1) {
|
|
2692
|
+
} else if (state == 1) {
|
|
2314
2693
|
if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);
|
|
2315
2694
|
else dest.push(part, source[i+1]);
|
|
2316
2695
|
}
|
|
@@ -2345,7 +2724,7 @@ var CodeMirror = (function() {
|
|
|
2345
2724
|
},
|
|
2346
2725
|
insertHeight: function(at, lines, height) {
|
|
2347
2726
|
this.height += height;
|
|
2348
|
-
this.lines.
|
|
2727
|
+
this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
|
|
2349
2728
|
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
|
|
2350
2729
|
},
|
|
2351
2730
|
iterN: function(at, n, op) {
|
|
@@ -2384,6 +2763,7 @@ var CodeMirror = (function() {
|
|
|
2384
2763
|
var lines = [];
|
|
2385
2764
|
this.collapse(lines);
|
|
2386
2765
|
this.children = [new LeafChunk(lines)];
|
|
2766
|
+
this.children[0].parent = this;
|
|
2387
2767
|
}
|
|
2388
2768
|
},
|
|
2389
2769
|
collapse: function(lines) {
|
|
@@ -2510,31 +2890,36 @@ var CodeMirror = (function() {
|
|
|
2510
2890
|
function History() {
|
|
2511
2891
|
this.time = 0;
|
|
2512
2892
|
this.done = []; this.undone = [];
|
|
2893
|
+
this.compound = 0;
|
|
2894
|
+
this.closed = false;
|
|
2513
2895
|
}
|
|
2514
2896
|
History.prototype = {
|
|
2515
2897
|
addChange: function(start, added, old) {
|
|
2516
2898
|
this.undone.length = 0;
|
|
2517
|
-
var time = +new Date,
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
for (var i = last.added - oldoff, e = old.length; i < e; ++i)
|
|
2534
|
-
last.old.push(old[i]);
|
|
2535
|
-
if (last.added < added) last.added = added;
|
|
2899
|
+
var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
|
|
2900
|
+
var dtime = time - this.time;
|
|
2901
|
+
|
|
2902
|
+
if (this.compound && cur && !this.closed) {
|
|
2903
|
+
cur.push({start: start, added: added, old: old});
|
|
2904
|
+
} else if (dtime > 400 || !last || this.closed ||
|
|
2905
|
+
last.start > start + old.length || last.start + last.added < start) {
|
|
2906
|
+
this.done.push([{start: start, added: added, old: old}]);
|
|
2907
|
+
this.closed = false;
|
|
2908
|
+
} else {
|
|
2909
|
+
var startBefore = Math.max(0, last.start - start),
|
|
2910
|
+
endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
|
|
2911
|
+
for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
|
|
2912
|
+
for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
|
|
2913
|
+
if (startBefore) last.start = start;
|
|
2914
|
+
last.added += added - (old.length - startBefore - endAfter);
|
|
2536
2915
|
}
|
|
2537
2916
|
this.time = time;
|
|
2917
|
+
},
|
|
2918
|
+
startCompound: function() {
|
|
2919
|
+
if (!this.compound++) this.closed = true;
|
|
2920
|
+
},
|
|
2921
|
+
endCompound: function() {
|
|
2922
|
+
if (!--this.compound) this.closed = true;
|
|
2538
2923
|
}
|
|
2539
2924
|
};
|
|
2540
2925
|
|
|
@@ -2566,14 +2951,20 @@ var CodeMirror = (function() {
|
|
|
2566
2951
|
else if (e.button & 4) return 2;
|
|
2567
2952
|
}
|
|
2568
2953
|
|
|
2954
|
+
// Allow 3rd-party code to override event properties by adding an override
|
|
2955
|
+
// object to an event object.
|
|
2956
|
+
function e_prop(e, prop) {
|
|
2957
|
+
var overridden = e.override && e.override.hasOwnProperty(prop);
|
|
2958
|
+
return overridden ? e.override[prop] : e[prop];
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2569
2961
|
// Event handler registration. If disconnect is true, it'll return a
|
|
2570
2962
|
// function that unregisters the handler.
|
|
2571
2963
|
function connect(node, type, handler, disconnect) {
|
|
2572
2964
|
if (typeof node.addEventListener == "function") {
|
|
2573
2965
|
node.addEventListener(type, handler, false);
|
|
2574
2966
|
if (disconnect) return function() {node.removeEventListener(type, handler, false);};
|
|
2575
|
-
}
|
|
2576
|
-
else {
|
|
2967
|
+
} else {
|
|
2577
2968
|
var wrapHandler = function(event) {handler(event || window.event);};
|
|
2578
2969
|
node.attachEvent("on" + type, wrapHandler);
|
|
2579
2970
|
if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);};
|
|
@@ -2584,26 +2975,48 @@ var CodeMirror = (function() {
|
|
|
2584
2975
|
function Delayed() {this.id = null;}
|
|
2585
2976
|
Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
|
|
2586
2977
|
|
|
2587
|
-
|
|
2588
|
-
var dragAndDrop = function() {
|
|
2589
|
-
// IE8 has ondragstart and ondrop properties, but doesn't seem to
|
|
2590
|
-
// actually support ondragstart the way it's supposed to work.
|
|
2591
|
-
if (/MSIE [1-8]\b/.test(navigator.userAgent)) return false;
|
|
2592
|
-
var div = document.createElement('div');
|
|
2593
|
-
return "draggable" in div;
|
|
2594
|
-
}();
|
|
2978
|
+
var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
|
|
2595
2979
|
|
|
2596
2980
|
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
|
|
2597
2981
|
var ie = /MSIE \d/.test(navigator.userAgent);
|
|
2982
|
+
var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
|
|
2983
|
+
var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
|
|
2984
|
+
var quirksMode = ie && document.documentMode == 5;
|
|
2598
2985
|
var webkit = /WebKit\//.test(navigator.userAgent);
|
|
2986
|
+
var chrome = /Chrome\//.test(navigator.userAgent);
|
|
2987
|
+
var opera = /Opera\//.test(navigator.userAgent);
|
|
2988
|
+
var safari = /Apple Computer/.test(navigator.vendor);
|
|
2989
|
+
var khtml = /KHTML\//.test(navigator.userAgent);
|
|
2990
|
+
var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);
|
|
2991
|
+
|
|
2992
|
+
// Detect drag-and-drop
|
|
2993
|
+
var dragAndDrop = function() {
|
|
2994
|
+
// There is *some* kind of drag-and-drop support in IE6-8, but I
|
|
2995
|
+
// couldn't get it to work yet.
|
|
2996
|
+
if (ie_lt9) return false;
|
|
2997
|
+
var div = document.createElement('div');
|
|
2998
|
+
return "draggable" in div || "dragDrop" in div;
|
|
2999
|
+
}();
|
|
2599
3000
|
|
|
2600
|
-
var lineSep = "\n";
|
|
2601
3001
|
// Feature-detect whether newlines in textareas are converted to \r\n
|
|
2602
|
-
|
|
3002
|
+
var lineSep = function () {
|
|
2603
3003
|
var te = document.createElement("textarea");
|
|
2604
3004
|
te.value = "foo\nbar";
|
|
2605
|
-
if (te.value.indexOf("\r") > -1)
|
|
2606
|
-
|
|
3005
|
+
if (te.value.indexOf("\r") > -1) return "\r\n";
|
|
3006
|
+
return "\n";
|
|
3007
|
+
}();
|
|
3008
|
+
|
|
3009
|
+
// For a reason I have yet to figure out, some browsers disallow
|
|
3010
|
+
// word wrapping between certain characters *only* if a new inline
|
|
3011
|
+
// element is started between them. This makes it hard to reliably
|
|
3012
|
+
// measure the position of things, since that requires inserting an
|
|
3013
|
+
// extra span. This terribly fragile set of regexps matches the
|
|
3014
|
+
// character combinations that suffer from this phenomenon on the
|
|
3015
|
+
// various browsers.
|
|
3016
|
+
var spanAffectsWrapping = /^$/; // Won't match any two-character string
|
|
3017
|
+
if (gecko) spanAffectsWrapping = /$'/;
|
|
3018
|
+
else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
|
|
3019
|
+
else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
|
|
2607
3020
|
|
|
2608
3021
|
// Counts the column offset in a string, taking tabs into account.
|
|
2609
3022
|
// Used mostly to find indentation.
|
|
@@ -2665,6 +3078,12 @@ var CodeMirror = (function() {
|
|
|
2665
3078
|
function eltText(node) {
|
|
2666
3079
|
return node.textContent || node.innerText || node.nodeValue || "";
|
|
2667
3080
|
}
|
|
3081
|
+
function selectInput(node) {
|
|
3082
|
+
if (ios) { // Mobile Safari apparently has a bug where select() is broken.
|
|
3083
|
+
node.selectionStart = 0;
|
|
3084
|
+
node.selectionEnd = node.value.length;
|
|
3085
|
+
} else node.select();
|
|
3086
|
+
}
|
|
2668
3087
|
|
|
2669
3088
|
// Operations on {line, ch} objects.
|
|
2670
3089
|
function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
|
|
@@ -2678,24 +3097,25 @@ var CodeMirror = (function() {
|
|
|
2678
3097
|
}
|
|
2679
3098
|
// Recent (late 2011) Opera betas insert bogus newlines at the start
|
|
2680
3099
|
// of the textContent, so we strip those.
|
|
2681
|
-
if (htmlEscape("a") == "\na")
|
|
3100
|
+
if (htmlEscape("a") == "\na") {
|
|
2682
3101
|
htmlEscape = function(str) {
|
|
2683
3102
|
escapeElement.textContent = str;
|
|
2684
3103
|
return escapeElement.innerHTML.slice(1);
|
|
2685
3104
|
};
|
|
2686
3105
|
// Some IEs don't preserve tabs through innerHTML
|
|
2687
|
-
else if (htmlEscape("\t") != "\t")
|
|
3106
|
+
} else if (htmlEscape("\t") != "\t") {
|
|
2688
3107
|
htmlEscape = function(str) {
|
|
2689
3108
|
escapeElement.innerHTML = "";
|
|
2690
3109
|
escapeElement.appendChild(document.createTextNode(str));
|
|
2691
3110
|
return escapeElement.innerHTML;
|
|
2692
3111
|
};
|
|
3112
|
+
}
|
|
2693
3113
|
CodeMirror.htmlEscape = htmlEscape;
|
|
2694
3114
|
|
|
2695
3115
|
// Used to position the cursor after an undo/redo by finding the
|
|
2696
3116
|
// last edited character.
|
|
2697
3117
|
function editEnd(from, to) {
|
|
2698
|
-
if (!to) return
|
|
3118
|
+
if (!to) return 0;
|
|
2699
3119
|
if (!from) return to.length;
|
|
2700
3120
|
for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)
|
|
2701
3121
|
if (from.charAt(i) != to.charAt(j)) break;
|
|
@@ -2743,10 +3163,10 @@ var CodeMirror = (function() {
|
|
|
2743
3163
|
var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
|
|
2744
3164
|
19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
|
|
2745
3165
|
36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
|
|
2746
|
-
46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod",
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
63233: "Down", 63302: "Insert", 63272: "Delete"};
|
|
3166
|
+
46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
|
|
3167
|
+
186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
|
|
3168
|
+
221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
|
|
3169
|
+
63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
|
|
2750
3170
|
CodeMirror.keyNames = keyNames;
|
|
2751
3171
|
(function() {
|
|
2752
3172
|
// Number keys
|