codemirror-rails 2.32 → 2.33
Sign up to get free protection for your applications and to get access to all the features.
- data/codemirror-rails.gemspec +1 -1
- data/lib/codemirror/rails/version.rb +2 -2
- data/vendor/assets/javascripts/codemirror.js +355 -349
- data/vendor/assets/javascripts/codemirror/keymaps/vim.js +6 -5
- data/vendor/assets/javascripts/codemirror/modes/clike.js +6 -2
- data/vendor/assets/javascripts/codemirror/modes/clojure.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +3 -3
- data/vendor/assets/javascripts/codemirror/modes/css.js +52 -2
- data/vendor/assets/javascripts/codemirror/modes/ecl.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/gfm.js +4 -3
- data/vendor/assets/javascripts/codemirror/modes/go.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/groovy.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/haskell.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/haxe.js +4 -4
- data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +3 -3
- data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/javascript.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/less.js +94 -60
- data/vendor/assets/javascripts/codemirror/modes/markdown.js +4 -4
- data/vendor/assets/javascripts/codemirror/modes/ntriples.js +4 -4
- data/vendor/assets/javascripts/codemirror/modes/ocaml.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/pascal.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/perl.js +71 -71
- data/vendor/assets/javascripts/codemirror/modes/php.js +3 -3
- data/vendor/assets/javascripts/codemirror/modes/pig.js +3 -3
- data/vendor/assets/javascripts/codemirror/modes/python.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/scheme.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/shell.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/sieve.js +156 -0
- data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/smarty.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/stex.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/tiki.js +4 -4
- data/vendor/assets/javascripts/codemirror/modes/velocity.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/verilog.js +1 -1
- data/vendor/assets/javascripts/codemirror/modes/xml.js +2 -2
- data/vendor/assets/javascripts/codemirror/modes/xquery.js +7 -4
- data/vendor/assets/javascripts/codemirror/utils/dialog.js +4 -1
- data/vendor/assets/javascripts/codemirror/utils/formatting.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +3 -3
- data/vendor/assets/javascripts/codemirror/utils/loadmode.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/multiplex.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/pig-hint.js +1 -1
- data/vendor/assets/javascripts/codemirror/utils/runmode.js +8 -4
- data/vendor/assets/javascripts/codemirror/utils/search.js +4 -4
- data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +13 -11
- data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +89 -68
- data/vendor/assets/javascripts/codemirror/utils/xml-hint.js +8 -8
- data/vendor/assets/stylesheets/codemirror.css +15 -11
- metadata +13 -13
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']
|
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,11 +1,12 @@
|
|
1
|
-
// CodeMirror version 2.
|
1
|
+
// CodeMirror version 2.33
|
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,
|
5
5
|
// some utilities are defined.
|
6
6
|
|
7
7
|
// CodeMirror is the only global var we claim
|
8
|
-
|
8
|
+
window.CodeMirror = (function() {
|
9
|
+
"use strict";
|
9
10
|
// This is the function that produces an editor instance. Its
|
10
11
|
// closure is used to store the editor state.
|
11
12
|
function CodeMirror(place, givenOptions) {
|
@@ -15,38 +16,33 @@ var CodeMirror = (function() {
|
|
15
16
|
if (defaults.hasOwnProperty(opt))
|
16
17
|
options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
|
17
18
|
|
19
|
+
var input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em");
|
20
|
+
input.setAttribute("wrap", "off"); input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off");
|
21
|
+
// Wraps and hides input textarea
|
22
|
+
var inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
|
23
|
+
// The empty scrollbar content, used solely for managing the scrollbar thumb.
|
24
|
+
var scrollbarInner = elt("div", null, "CodeMirror-scrollbar-inner");
|
25
|
+
// The vertical scrollbar. Horizontal scrolling is handled by the scroller itself.
|
26
|
+
var scrollbar = elt("div", [scrollbarInner], "CodeMirror-scrollbar");
|
27
|
+
// DIVs containing the selection and the actual code
|
28
|
+
var lineDiv = elt("div"), selectionDiv = elt("div", null, null, "position: relative; z-index: -1");
|
29
|
+
// Blinky cursor, and element used to ensure cursor fits at the end of a line
|
30
|
+
var cursor = elt("pre", "\u00a0", "CodeMirror-cursor"), widthForcer = elt("pre", "\u00a0", "CodeMirror-cursor", "visibility: hidden");
|
31
|
+
// Used to measure text size
|
32
|
+
var measure = elt("div", null, null, "position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;");
|
33
|
+
var lineSpace = elt("div", [measure, cursor, widthForcer, selectionDiv, lineDiv], null, "position: relative; z-index: 0");
|
34
|
+
var gutterText = elt("div", null, "CodeMirror-gutter-text"), gutter = elt("div", [gutterText], "CodeMirror-gutter");
|
35
|
+
// Moved around its parent to cover visible view
|
36
|
+
var mover = elt("div", [gutter, elt("div", [lineSpace], "CodeMirror-lines")], null, "position: relative");
|
37
|
+
// Set to the height of the text, causes scrolling
|
38
|
+
var sizer = elt("div", [mover], null, "position: relative");
|
39
|
+
// Provides scrolling
|
40
|
+
var scroller = elt("div", [sizer], "CodeMirror-scroll");
|
41
|
+
scroller.setAttribute("tabIndex", "-1");
|
18
42
|
// The element in which the editor lives.
|
19
|
-
var wrapper =
|
20
|
-
wrapper.className = "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "");
|
21
|
-
// This mess creates the base DOM structure for the editor.
|
22
|
-
wrapper.innerHTML =
|
23
|
-
'<div style="overflow: hidden; position: relative; width: 3px; height: 0px;">' + // Wraps and hides input textarea
|
24
|
-
'<textarea style="position: absolute; padding: 0; width: 1px; height: 1em" wrap="off" ' +
|
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.
|
29
|
-
'<div class="CodeMirror-scroll" tabindex="-1">' +
|
30
|
-
'<div style="position: relative">' + // Set to the height of the text, causes scrolling
|
31
|
-
'<div style="position: relative">' + // Moved around its parent to cover visible view
|
32
|
-
'<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
|
33
|
-
// Provides positioning relative to (visible) text origin
|
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: 0px; overflow: hidden; visibility: hidden;"></div>' +
|
37
|
-
'<pre class="CodeMirror-cursor"> </pre>' + // Absolutely positioned blinky cursor
|
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
|
40
|
-
'</div></div></div></div></div>';
|
43
|
+
var wrapper = elt("div", [inputDiv, scrollbar, scroller], "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : ""));
|
41
44
|
if (place.appendChild) place.appendChild(wrapper); else place(wrapper);
|
42
|
-
|
43
|
-
var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,
|
44
|
-
scroller = wrapper.lastChild, code = scroller.firstChild,
|
45
|
-
mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,
|
46
|
-
lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
|
47
|
-
cursor = measure.nextSibling, widthForcer = cursor.nextSibling,
|
48
|
-
selectionDiv = widthForcer.nextSibling, lineDiv = selectionDiv.nextSibling,
|
49
|
-
scrollbar = inputDiv.nextSibling, scrollbarInner = scrollbar.firstChild;
|
45
|
+
|
50
46
|
themeChanged(); keyMapChanged();
|
51
47
|
// Needed to hide big blue blinking cursor on Mobile Safari
|
52
48
|
if (ios) input.style.width = "0px";
|
@@ -58,20 +54,17 @@ var CodeMirror = (function() {
|
|
58
54
|
// Needed to handle Tab key in KHTML
|
59
55
|
if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute";
|
60
56
|
|
61
|
-
// Check for OS X >= 10.7.
|
62
|
-
//
|
63
|
-
//
|
64
|
-
//
|
65
|
-
if (mac_geLion) {
|
66
|
-
|
67
|
-
|
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
|
-
}
|
57
|
+
// Check for OS X >= 10.7. This has transparent scrollbars, so the
|
58
|
+
// overlaying of one scrollbar with another won't work. This is a
|
59
|
+
// temporary hack to simply turn off the overlay scrollbar. See
|
60
|
+
// issue #727.
|
61
|
+
if (mac_geLion) { scrollbar.style.zIndex = -2; scrollbar.style.visibility = "hidden"; }
|
62
|
+
// Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
|
63
|
+
else if (ie_lt8) scrollbar.style.minWidth = "18px";
|
71
64
|
|
72
65
|
// Check for problem with IE innerHTML not working when we have a
|
73
66
|
// P (or similar) parent node.
|
74
|
-
try {
|
67
|
+
try { charWidth(); }
|
75
68
|
catch (e) {
|
76
69
|
if (e.message.match(/runtime/i))
|
77
70
|
e = new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)");
|
@@ -92,7 +85,7 @@ var CodeMirror = (function() {
|
|
92
85
|
var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};
|
93
86
|
// Selection-related flags. shiftSelecting obviously tracks
|
94
87
|
// whether the user is holding shift.
|
95
|
-
var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0,
|
88
|
+
var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, draggingText,
|
96
89
|
overwrite = false, suppressEdits = false;
|
97
90
|
// Variables used by startOperation/endOperation to track what
|
98
91
|
// happened during the operation.
|
@@ -105,8 +98,10 @@ var CodeMirror = (function() {
|
|
105
98
|
var bracketHighlighted;
|
106
99
|
// Tracks the maximum line length so that the horizontal scrollbar
|
107
100
|
// can be kept static when scrolling.
|
108
|
-
var maxLine =
|
101
|
+
var maxLine = getLine(0), updateMaxLine = false, maxLineChanged = true;
|
109
102
|
var tabCache = {};
|
103
|
+
var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
|
104
|
+
var goalColumn = null;
|
110
105
|
|
111
106
|
// Initialize the content.
|
112
107
|
operation(function(){setValue(options.value || ""); updateInput = false;})();
|
@@ -120,12 +115,13 @@ var CodeMirror = (function() {
|
|
120
115
|
// which point we can't mess with it anymore. Context menu is
|
121
116
|
// handled in onMouseDown for Gecko.
|
122
117
|
if (!gecko) connect(scroller, "contextmenu", onContextMenu);
|
123
|
-
connect(scroller, "scroll",
|
124
|
-
connect(scrollbar, "scroll",
|
118
|
+
connect(scroller, "scroll", onScrollMain);
|
119
|
+
connect(scrollbar, "scroll", onScrollBar);
|
125
120
|
connect(scrollbar, "mousedown", function() {if (focused) setTimeout(focusInput, 0);});
|
126
|
-
connect(
|
127
|
-
|
128
|
-
|
121
|
+
var resizeHandler = connect(window, "resize", function() {
|
122
|
+
if (wrapper.parentNode) updateDisplay(true);
|
123
|
+
else resizeHandler();
|
124
|
+
}, true);
|
129
125
|
connect(input, "keyup", operation(onKeyUp));
|
130
126
|
connect(input, "input", fastPoll);
|
131
127
|
connect(input, "keydown", operation(onKeyDown));
|
@@ -133,12 +129,12 @@ var CodeMirror = (function() {
|
|
133
129
|
connect(input, "focus", onFocus);
|
134
130
|
connect(input, "blur", onBlur);
|
135
131
|
|
132
|
+
function drag_(e) {
|
133
|
+
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
|
134
|
+
e_stop(e);
|
135
|
+
}
|
136
136
|
if (options.dragDrop) {
|
137
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
138
|
connect(scroller, "dragenter", drag_);
|
143
139
|
connect(scroller, "dragover", drag_);
|
144
140
|
connect(scroller, "drop", operation(onDrop));
|
@@ -150,7 +146,7 @@ var CodeMirror = (function() {
|
|
150
146
|
}));
|
151
147
|
|
152
148
|
// Needed to handle Tab key in KHTML
|
153
|
-
if (khtml) connect(
|
149
|
+
if (khtml) connect(sizer, "mouseup", function() {
|
154
150
|
if (document.activeElement == input) input.blur();
|
155
151
|
focusInput();
|
156
152
|
});
|
@@ -183,7 +179,8 @@ var CodeMirror = (function() {
|
|
183
179
|
else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
|
184
180
|
else if (option == "tabSize") updateDisplay(true);
|
185
181
|
else if (option == "keyMap") keyMapChanged();
|
186
|
-
if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" ||
|
182
|
+
if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" ||
|
183
|
+
option == "theme" || option == "lineNumberFormatter") {
|
187
184
|
gutterChanged();
|
188
185
|
updateDisplay(true);
|
189
186
|
}
|
@@ -213,7 +210,7 @@ var CodeMirror = (function() {
|
|
213
210
|
matchBrackets: operation(function(){matchBrackets(true);}),
|
214
211
|
getTokenAt: operation(function(pos) {
|
215
212
|
pos = clipPos(pos);
|
216
|
-
return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);
|
213
|
+
return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), options.tabSize, pos.ch);
|
217
214
|
}),
|
218
215
|
getStateAfter: function(line) {
|
219
216
|
line = clipLine(line == null ? doc.size - 1: line);
|
@@ -250,15 +247,16 @@ var CodeMirror = (function() {
|
|
250
247
|
return line;
|
251
248
|
},
|
252
249
|
lineInfo: lineInfo,
|
250
|
+
getViewport: function() { return {from: showingFrom, to: showingTo};},
|
253
251
|
addWidget: function(pos, node, scroll, vert, horiz) {
|
254
252
|
pos = localCoords(clipPos(pos));
|
255
253
|
var top = pos.yBot, left = pos.x;
|
256
254
|
node.style.position = "absolute";
|
257
|
-
|
255
|
+
sizer.appendChild(node);
|
258
256
|
if (vert == "over") top = pos.y;
|
259
257
|
else if (vert == "near") {
|
260
258
|
var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),
|
261
|
-
hspace = Math.max(
|
259
|
+
hspace = Math.max(sizer.clientWidth, lineSpace.clientWidth) - paddingLeft();
|
262
260
|
if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)
|
263
261
|
top = pos.y - node.offsetHeight;
|
264
262
|
if (left + node.offsetWidth > hspace)
|
@@ -267,11 +265,11 @@ var CodeMirror = (function() {
|
|
267
265
|
node.style.top = (top + paddingTop()) + "px";
|
268
266
|
node.style.left = node.style.right = "";
|
269
267
|
if (horiz == "right") {
|
270
|
-
left =
|
268
|
+
left = sizer.clientWidth - node.offsetWidth;
|
271
269
|
node.style.right = "0px";
|
272
270
|
} else {
|
273
271
|
if (horiz == "left") left = 0;
|
274
|
-
else if (horiz == "middle") left = (
|
272
|
+
else if (horiz == "middle") left = (sizer.clientWidth - node.offsetWidth) / 2;
|
275
273
|
node.style.left = (left + paddingLeft()) + "px";
|
276
274
|
}
|
277
275
|
if (scroll)
|
@@ -339,7 +337,7 @@ var CodeMirror = (function() {
|
|
339
337
|
},
|
340
338
|
scrollTo: function(x, y) {
|
341
339
|
if (x != null) scroller.scrollLeft = x;
|
342
|
-
if (y != null) scrollbar.scrollTop = y;
|
340
|
+
if (y != null) scrollbar.scrollTop = scroller.scrollTop = y;
|
343
341
|
updateDisplay([]);
|
344
342
|
},
|
345
343
|
getScrollInfo: function() {
|
@@ -353,6 +351,7 @@ var CodeMirror = (function() {
|
|
353
351
|
}
|
354
352
|
if (width != null) wrapper.style.width = interpret(width);
|
355
353
|
if (height != null) scroller.style.height = interpret(height);
|
354
|
+
instance.refresh();
|
356
355
|
},
|
357
356
|
|
358
357
|
operation: function(f){return operation(f)();},
|
@@ -387,25 +386,30 @@ var CodeMirror = (function() {
|
|
387
386
|
return text.join(lineSep || "\n");
|
388
387
|
}
|
389
388
|
|
390
|
-
function
|
391
|
-
if (
|
392
|
-
|
393
|
-
|
389
|
+
function onScrollBar(e) {
|
390
|
+
if (scrollbar.scrollTop != lastScrollTop) {
|
391
|
+
lastScrollTop = scroller.scrollTop = scrollbar.scrollTop;
|
392
|
+
updateDisplay([]);
|
394
393
|
}
|
395
|
-
|
396
|
-
|
397
|
-
|
394
|
+
}
|
395
|
+
|
396
|
+
function onScrollMain(e) {
|
397
|
+
if (options.fixedGutter && gutter.style.left != scroller.scrollLeft + "px")
|
398
|
+
gutter.style.left = scroller.scrollLeft + "px";
|
399
|
+
if (scroller.scrollTop != lastScrollTop) {
|
400
|
+
lastScrollTop = scroller.scrollTop;
|
401
|
+
if (scrollbar.scrollTop != lastScrollTop)
|
402
|
+
scrollbar.scrollTop = lastScrollTop;
|
398
403
|
updateDisplay([]);
|
399
|
-
if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + "px";
|
400
|
-
if (options.onScroll) options.onScroll(instance);
|
401
404
|
}
|
405
|
+
if (options.onScroll) options.onScroll(instance);
|
402
406
|
}
|
403
407
|
|
404
408
|
function onMouseDown(e) {
|
405
409
|
setShift(e_prop(e, "shiftKey"));
|
406
410
|
// Check whether this is a click in a widget
|
407
411
|
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
408
|
-
if (n.parentNode ==
|
412
|
+
if (n.parentNode == sizer && n != mover) return;
|
409
413
|
|
410
414
|
// See if this is a click in the gutter
|
411
415
|
for (var n = e_target(e); n != wrapper; n = n.parentNode)
|
@@ -448,21 +452,21 @@ var CodeMirror = (function() {
|
|
448
452
|
setSelectionUser(word.from, word.to);
|
449
453
|
} else { lastClick = {time: now, pos: start}; }
|
450
454
|
|
455
|
+
function dragEnd(e2) {
|
456
|
+
if (webkit) scroller.draggable = false;
|
457
|
+
draggingText = false;
|
458
|
+
up(); drop();
|
459
|
+
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
|
460
|
+
e_preventDefault(e2);
|
461
|
+
setCursor(start.line, start.ch, true);
|
462
|
+
focusInput();
|
463
|
+
}
|
464
|
+
}
|
451
465
|
var last = start, going;
|
452
466
|
if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
|
453
467
|
!posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
|
454
468
|
// Let the drag handler handle this.
|
455
469
|
if (webkit) scroller.draggable = true;
|
456
|
-
function dragEnd(e2) {
|
457
|
-
if (webkit) scroller.draggable = false;
|
458
|
-
draggingText = false;
|
459
|
-
up(); drop();
|
460
|
-
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
|
461
|
-
e_preventDefault(e2);
|
462
|
-
setCursor(start.line, start.ch, true);
|
463
|
-
focusInput();
|
464
|
-
}
|
465
|
-
}
|
466
470
|
var up = connect(document, "mouseup", operation(dragEnd), true);
|
467
471
|
var drop = connect(scroller, "drop", operation(dragEnd), true);
|
468
472
|
draggingText = true;
|
@@ -525,11 +529,12 @@ var CodeMirror = (function() {
|
|
525
529
|
}
|
526
530
|
function onDrop(e) {
|
527
531
|
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
|
528
|
-
e
|
532
|
+
e_preventDefault(e);
|
529
533
|
var pos = posFromMouse(e, true), files = e.dataTransfer.files;
|
530
534
|
if (!pos || options.readOnly) return;
|
531
535
|
if (files && files.length && window.FileReader && window.File) {
|
532
|
-
|
536
|
+
var n = files.length, text = Array(n), read = 0;
|
537
|
+
var loadFile = function(file, i) {
|
533
538
|
var reader = new FileReader;
|
534
539
|
reader.onload = function() {
|
535
540
|
text[i] = reader.result;
|
@@ -542,8 +547,7 @@ var CodeMirror = (function() {
|
|
542
547
|
}
|
543
548
|
};
|
544
549
|
reader.readAsText(file);
|
545
|
-
}
|
546
|
-
var n = files.length, text = Array(n), read = 0;
|
550
|
+
};
|
547
551
|
for (var i = 0; i < n; ++i) loadFile(files[i], i);
|
548
552
|
} else {
|
549
553
|
// Don't do a replace if the drop happened inside of the selected text.
|
@@ -566,10 +570,10 @@ var CodeMirror = (function() {
|
|
566
570
|
function onDragStart(e) {
|
567
571
|
var txt = getSelection();
|
568
572
|
e.dataTransfer.setData("Text", txt);
|
569
|
-
|
573
|
+
|
570
574
|
// Use dummy image instead of default browsers image.
|
571
575
|
if (gecko || chrome || opera) {
|
572
|
-
var img =
|
576
|
+
var img = elt('img');
|
573
577
|
img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image
|
574
578
|
e.dataTransfer.setDragImage(img, 0, 0);
|
575
579
|
}
|
@@ -594,6 +598,7 @@ var CodeMirror = (function() {
|
|
594
598
|
}
|
595
599
|
return true;
|
596
600
|
}
|
601
|
+
var maybeTransition;
|
597
602
|
function handleKeyBinding(e) {
|
598
603
|
// Handle auto keymap transitions
|
599
604
|
var startMap = getKeyMap(options.keyMap), next = startMap.auto;
|
@@ -640,7 +645,7 @@ var CodeMirror = (function() {
|
|
640
645
|
return handled;
|
641
646
|
}
|
642
647
|
|
643
|
-
var lastStoppedKey = null
|
648
|
+
var lastStoppedKey = null;
|
644
649
|
function onKeyDown(e) {
|
645
650
|
if (!focused) onFocus();
|
646
651
|
if (ie && e.keyCode == 27) { e.returnValue = false; }
|
@@ -703,42 +708,6 @@ var CodeMirror = (function() {
|
|
703
708
|
setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);
|
704
709
|
}
|
705
710
|
|
706
|
-
function chopDelta(delta) {
|
707
|
-
// Make sure we always scroll a little bit for any nonzero delta.
|
708
|
-
if (delta > 0.0 && delta < 1.0) return 1;
|
709
|
-
else if (delta > -1.0 && delta < 0.0) return -1;
|
710
|
-
else return Math.round(delta);
|
711
|
-
}
|
712
|
-
|
713
|
-
function onMouseWheel(e) {
|
714
|
-
var deltaX = 0, deltaY = 0;
|
715
|
-
if (e.type == "DOMMouseScroll") { // Firefox
|
716
|
-
var delta = -e.detail * 8.0;
|
717
|
-
if (e.axis == e.HORIZONTAL_AXIS) deltaX = delta;
|
718
|
-
else if (e.axis == e.VERTICAL_AXIS) deltaY = delta;
|
719
|
-
} else if (e.wheelDeltaX !== undefined && e.wheelDeltaY !== undefined) { // WebKit
|
720
|
-
deltaX = e.wheelDeltaX / 3.0;
|
721
|
-
deltaY = e.wheelDeltaY / 3.0;
|
722
|
-
} else if (e.wheelDelta !== undefined) { // IE or Opera
|
723
|
-
deltaY = e.wheelDelta / 3.0;
|
724
|
-
}
|
725
|
-
|
726
|
-
var scrolled = false;
|
727
|
-
deltaX = chopDelta(deltaX);
|
728
|
-
deltaY = chopDelta(deltaY);
|
729
|
-
if ((deltaX > 0 && scroller.scrollLeft > 0) ||
|
730
|
-
(deltaX < 0 && scroller.scrollLeft + scroller.clientWidth < scroller.scrollWidth)) {
|
731
|
-
scroller.scrollLeft -= deltaX;
|
732
|
-
scrolled = true;
|
733
|
-
}
|
734
|
-
if ((deltaY > 0 && scrollbar.scrollTop > 0) ||
|
735
|
-
(deltaY < 0 && scrollbar.scrollTop + scrollbar.clientHeight < scrollbar.scrollHeight)) {
|
736
|
-
scrollbar.scrollTop -= deltaY;
|
737
|
-
scrolled = true;
|
738
|
-
}
|
739
|
-
if (scrolled) e_stop(e);
|
740
|
-
}
|
741
|
-
|
742
711
|
// Replace the range from from to to by the strings in newText.
|
743
712
|
// Afterwards, set the selection to selFrom, selTo.
|
744
713
|
function updateLines(from, to, newText, selFrom, selTo) {
|
@@ -771,7 +740,7 @@ var CodeMirror = (function() {
|
|
771
740
|
|
772
741
|
function updateLinesNoUndo(from, to, newText, selFrom, selTo) {
|
773
742
|
if (suppressEdits) return;
|
774
|
-
var recomputeMaxLength = false, maxLineLength = maxLine.length;
|
743
|
+
var recomputeMaxLength = false, maxLineLength = maxLine.text.length;
|
775
744
|
if (!options.lineWrapping)
|
776
745
|
doc.iter(from.line, to.line + 1, function(line) {
|
777
746
|
if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
|
@@ -831,7 +800,7 @@ var CodeMirror = (function() {
|
|
831
800
|
doc.iter(from.line, from.line + newText.length, function(line) {
|
832
801
|
var l = line.text;
|
833
802
|
if (!line.hidden && l.length > maxLineLength) {
|
834
|
-
maxLine =
|
803
|
+
maxLine = line; maxLineLength = l.length; maxLineChanged = true;
|
835
804
|
recomputeMaxLength = false;
|
836
805
|
}
|
837
806
|
});
|
@@ -867,46 +836,43 @@ var CodeMirror = (function() {
|
|
867
836
|
|
868
837
|
function needsScrollbar() {
|
869
838
|
var realHeight = doc.height * textHeight() + 2 * paddingTop();
|
870
|
-
return realHeight
|
839
|
+
return realHeight * .99 > scroller.offsetHeight ? realHeight : false;
|
871
840
|
}
|
872
841
|
|
873
842
|
function updateVerticalScroll(scrollTop) {
|
874
843
|
var scrollHeight = needsScrollbar();
|
875
844
|
scrollbar.style.display = scrollHeight ? "block" : "none";
|
876
845
|
if (scrollHeight) {
|
877
|
-
scrollbarInner.style.height = scrollHeight + "px";
|
878
|
-
scrollbar.style.height = scroller.
|
879
|
-
if (scrollTop != null)
|
846
|
+
scrollbarInner.style.height = sizer.style.minHeight = scrollHeight + "px";
|
847
|
+
scrollbar.style.height = scroller.clientHeight + "px";
|
848
|
+
if (scrollTop != null) {
|
849
|
+
scrollbar.scrollTop = scroller.scrollTop = scrollTop;
|
850
|
+
// 'Nudge' the scrollbar to work around a Webkit bug where,
|
851
|
+
// in some situations, we'd end up with a scrollbar that
|
852
|
+
// reported its scrollTop (and looked) as expected, but
|
853
|
+
// *behaved* as if it was still in a previous state (i.e.
|
854
|
+
// couldn't scroll up, even though it appeared to be at the
|
855
|
+
// bottom).
|
856
|
+
if (webkit) setTimeout(function() {
|
857
|
+
if (scrollbar.scrollTop != scrollTop) return;
|
858
|
+
scrollbar.scrollTop = scrollTop + (scrollTop ? -1 : 1);
|
859
|
+
scrollbar.scrollTop = scrollTop;
|
860
|
+
}, 0);
|
861
|
+
}
|
862
|
+
} else {
|
863
|
+
sizer.style.minHeight = "";
|
880
864
|
}
|
881
865
|
// Position the mover div to align with the current virtual scroll position
|
882
|
-
mover.style.top =
|
883
|
-
}
|
884
|
-
|
885
|
-
// On Mac OS X Lion and up, detect whether the mouse is plugged in by measuring
|
886
|
-
// the width of a div with a scrollbar in it. If the width is <= 1, then
|
887
|
-
// the mouse isn't plugged in and scrollbars should overlap the content.
|
888
|
-
function overlapScrollbars() {
|
889
|
-
var tmpSb = document.createElement('div'),
|
890
|
-
tmpSbInner = document.createElement('div');
|
891
|
-
tmpSb.className = "CodeMirror-scrollbar";
|
892
|
-
tmpSb.style.cssText = "position: absolute; left: -9999px; height: 100px;";
|
893
|
-
tmpSbInner.className = "CodeMirror-scrollbar-inner";
|
894
|
-
tmpSbInner.style.height = "200px";
|
895
|
-
tmpSb.appendChild(tmpSbInner);
|
896
|
-
|
897
|
-
document.body.appendChild(tmpSb);
|
898
|
-
var result = (tmpSb.offsetWidth <= 1);
|
899
|
-
document.body.removeChild(tmpSb);
|
900
|
-
return result;
|
866
|
+
mover.style.top = displayOffset * textHeight() + "px";
|
901
867
|
}
|
902
868
|
|
903
869
|
function computeMaxLength() {
|
904
|
-
|
905
|
-
|
906
|
-
doc.iter(
|
870
|
+
maxLine = getLine(0); maxLineChanged = true;
|
871
|
+
var maxLineLength = maxLine.text.length;
|
872
|
+
doc.iter(1, doc.size, function(line) {
|
907
873
|
var l = line.text;
|
908
874
|
if (!line.hidden && l.length > maxLineLength) {
|
909
|
-
maxLineLength = l.length; maxLine =
|
875
|
+
maxLineLength = l.length; maxLine = line;
|
910
876
|
}
|
911
877
|
});
|
912
878
|
updateMaxLine = false;
|
@@ -957,7 +923,6 @@ var CodeMirror = (function() {
|
|
957
923
|
return getRange(sel.from, sel.to, lineSep);
|
958
924
|
}
|
959
925
|
|
960
|
-
var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll
|
961
926
|
function slowPoll() {
|
962
927
|
if (pollingFast) return;
|
963
928
|
poll.set(options.pollInterval, function() {
|
@@ -1006,7 +971,7 @@ var CodeMirror = (function() {
|
|
1006
971
|
if (!posEq(sel.from, sel.to)) {
|
1007
972
|
prevInput = "";
|
1008
973
|
input.value = getSelection();
|
1009
|
-
selectInput(input);
|
974
|
+
if (focused) selectInput(input);
|
1010
975
|
} else if (user) prevInput = input.value = "";
|
1011
976
|
}
|
1012
977
|
|
@@ -1014,16 +979,23 @@ var CodeMirror = (function() {
|
|
1014
979
|
if (options.readOnly != "nocursor") input.focus();
|
1015
980
|
}
|
1016
981
|
|
1017
|
-
function scrollEditorIntoView() {
|
1018
|
-
var rect = cursor.getBoundingClientRect();
|
1019
|
-
// IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden
|
1020
|
-
if (ie && rect.top == rect.bottom) return;
|
1021
|
-
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
|
1022
|
-
if (rect.top < 0 || rect.bottom > winH) scrollCursorIntoView();
|
1023
|
-
}
|
1024
982
|
function scrollCursorIntoView() {
|
1025
983
|
var coords = calculateCursorCoords();
|
1026
|
-
|
984
|
+
scrollIntoView(coords.x, coords.y, coords.x, coords.yBot);
|
985
|
+
if (!focused) return;
|
986
|
+
var box = sizer.getBoundingClientRect(), doScroll = null;
|
987
|
+
if (coords.y + box.top < 0) doScroll = true;
|
988
|
+
else if (coords.y + box.top + textHeight() > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
|
989
|
+
if (doScroll != null) {
|
990
|
+
var hidden = cursor.style.display == "none";
|
991
|
+
if (hidden) {
|
992
|
+
cursor.style.display = "";
|
993
|
+
cursor.style.left = coords.x + "px";
|
994
|
+
cursor.style.top = (coords.y - displayOffset) + "px";
|
995
|
+
}
|
996
|
+
cursor.scrollIntoView(doScroll);
|
997
|
+
if (hidden) cursor.style.display = "none";
|
998
|
+
}
|
1027
999
|
}
|
1028
1000
|
function calculateCursorCoords() {
|
1029
1001
|
var cursor = localCoords(sel.inverted ? sel.from : sel.to);
|
@@ -1031,17 +1003,16 @@ var CodeMirror = (function() {
|
|
1031
1003
|
return {x: x, y: cursor.y, yBot: cursor.yBot};
|
1032
1004
|
}
|
1033
1005
|
function scrollIntoView(x1, y1, x2, y2) {
|
1034
|
-
var scrollPos = calculateScrollPos(x1, y1, x2, y2)
|
1035
|
-
if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft;
|
1036
|
-
if (scrollPos.scrollTop != null) {scrollbar.scrollTop =
|
1037
|
-
if (scrolled && options.onScroll) options.onScroll(instance);
|
1006
|
+
var scrollPos = calculateScrollPos(x1, y1, x2, y2);
|
1007
|
+
if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft;}
|
1008
|
+
if (scrollPos.scrollTop != null) {scrollbar.scrollTop = scroller.scrollTop = scrollPos.scrollTop;}
|
1038
1009
|
}
|
1039
1010
|
function calculateScrollPos(x1, y1, x2, y2) {
|
1040
1011
|
var pl = paddingLeft(), pt = paddingTop();
|
1041
1012
|
y1 += pt; y2 += pt; x1 += pl; x2 += pl;
|
1042
1013
|
var screen = scroller.clientHeight, screentop = scrollbar.scrollTop, result = {};
|
1043
|
-
var docBottom =
|
1044
|
-
var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10
|
1014
|
+
var docBottom = needsScrollbar() || Infinity;
|
1015
|
+
var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
|
1045
1016
|
if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
|
1046
1017
|
else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
|
1047
1018
|
|
@@ -1113,6 +1084,10 @@ var CodeMirror = (function() {
|
|
1113
1084
|
// This is just a bogus formula that detects when the editor is
|
1114
1085
|
// resized or the font size changes.
|
1115
1086
|
if (different) lastSizeC = scroller.clientHeight + th;
|
1087
|
+
if (from != showingFrom || to != showingTo && options.onViewportChange)
|
1088
|
+
setTimeout(function(){
|
1089
|
+
if (options.onViewportChange) options.onViewportChange(instance, from, to);
|
1090
|
+
});
|
1116
1091
|
showingFrom = from; showingTo = to;
|
1117
1092
|
displayOffset = heightAtLine(doc, from);
|
1118
1093
|
|
@@ -1125,6 +1100,10 @@ var CodeMirror = (function() {
|
|
1125
1100
|
function checkHeights() {
|
1126
1101
|
var curNode = lineDiv.firstChild, heightChanged = false;
|
1127
1102
|
doc.iter(showingFrom, showingTo, function(line) {
|
1103
|
+
// Work around bizarro IE7 bug where, sometimes, our curNode
|
1104
|
+
// is magically replaced with a new node in the DOM, leaving
|
1105
|
+
// us with a reference to an orphan (nextSibling-less) node.
|
1106
|
+
if (!curNode) return;
|
1128
1107
|
if (!line.hidden) {
|
1129
1108
|
var height = Math.round(curNode.offsetHeight / th) || 1;
|
1130
1109
|
if (line.height != height) {
|
@@ -1137,16 +1116,7 @@ var CodeMirror = (function() {
|
|
1137
1116
|
return heightChanged;
|
1138
1117
|
}
|
1139
1118
|
|
1140
|
-
if (options.lineWrapping)
|
1141
|
-
checkHeights();
|
1142
|
-
var scrollHeight = needsScrollbar();
|
1143
|
-
var shouldHaveScrollbar = scrollHeight ? "block" : "none";
|
1144
|
-
if (scrollbar.style.display != shouldHaveScrollbar) {
|
1145
|
-
scrollbar.style.display = shouldHaveScrollbar;
|
1146
|
-
if (scrollHeight) scrollbarInner.style.height = scrollHeight + "px";
|
1147
|
-
checkHeights();
|
1148
|
-
}
|
1149
|
-
}
|
1119
|
+
if (options.lineWrapping) checkHeights();
|
1150
1120
|
|
1151
1121
|
gutter.style.display = gutterDisplay;
|
1152
1122
|
if (different || gutterDirty) {
|
@@ -1183,14 +1153,14 @@ var CodeMirror = (function() {
|
|
1183
1153
|
}
|
1184
1154
|
|
1185
1155
|
function patchDisplay(from, to, intact) {
|
1156
|
+
function killNode(node) {
|
1157
|
+
var tmp = node.nextSibling;
|
1158
|
+
node.parentNode.removeChild(node);
|
1159
|
+
return tmp;
|
1160
|
+
}
|
1186
1161
|
// The first pass removes the DOM nodes that aren't intact.
|
1187
|
-
if (!intact.length) lineDiv
|
1162
|
+
if (!intact.length) removeChildren(lineDiv);
|
1188
1163
|
else {
|
1189
|
-
function killNode(node) {
|
1190
|
-
var tmp = node.nextSibling;
|
1191
|
-
node.parentNode.removeChild(node);
|
1192
|
-
return tmp;
|
1193
|
-
}
|
1194
1164
|
var domPos = 0, curNode = lineDiv.firstChild, n;
|
1195
1165
|
for (var i = 0; i < intact.length; ++i) {
|
1196
1166
|
var cur = intact[i];
|
@@ -1201,21 +1171,20 @@ var CodeMirror = (function() {
|
|
1201
1171
|
}
|
1202
1172
|
// This pass fills in the lines that actually changed.
|
1203
1173
|
var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;
|
1204
|
-
var scratch = document.createElement("div");
|
1205
1174
|
doc.iter(from, to, function(line) {
|
1206
1175
|
if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();
|
1207
1176
|
if (!nextIntact || nextIntact.from > j) {
|
1208
|
-
if (line.hidden) var
|
1177
|
+
if (line.hidden) var lineElement = elt("pre");
|
1209
1178
|
else {
|
1210
|
-
var
|
1211
|
-
|
1179
|
+
var lineElement = line.getElement(makeTab);
|
1180
|
+
if (line.className) lineElement.className = line.className;
|
1212
1181
|
// Kludge to make sure the styled element lies behind the selection (by z-index)
|
1213
|
-
if (line.bgClassName)
|
1214
|
-
|
1215
|
-
|
1182
|
+
if (line.bgClassName) {
|
1183
|
+
var pre = elt("pre", "\u00a0", line.bgClassName, "position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2");
|
1184
|
+
lineElement = elt("div", [pre, lineElement], null, "position: relative");
|
1185
|
+
}
|
1216
1186
|
}
|
1217
|
-
|
1218
|
-
lineDiv.insertBefore(scratch.firstChild, curNode);
|
1187
|
+
lineDiv.insertBefore(lineElement, curNode);
|
1219
1188
|
} else {
|
1220
1189
|
curNode = curNode.nextSibling;
|
1221
1190
|
}
|
@@ -1227,10 +1196,10 @@ var CodeMirror = (function() {
|
|
1227
1196
|
if (!options.gutter && !options.lineNumbers) return;
|
1228
1197
|
var hText = mover.offsetHeight, hEditor = scroller.clientHeight;
|
1229
1198
|
gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px";
|
1230
|
-
var
|
1199
|
+
var fragment = document.createDocumentFragment(), i = showingFrom, normalNode;
|
1231
1200
|
doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {
|
1232
1201
|
if (line.hidden) {
|
1233
|
-
|
1202
|
+
fragment.appendChild(elt("pre"));
|
1234
1203
|
} else {
|
1235
1204
|
var marker = line.gutterMarker;
|
1236
1205
|
var text = options.lineNumbers ? options.lineNumberFormatter(i + options.firstLineNumber) : null;
|
@@ -1238,15 +1207,18 @@ var CodeMirror = (function() {
|
|
1238
1207
|
text = marker.text.replace("%N%", text != null ? text : "");
|
1239
1208
|
else if (text == null)
|
1240
1209
|
text = "\u00a0";
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1210
|
+
var markerElement = fragment.appendChild(elt("pre", null, marker && marker.style));
|
1211
|
+
markerElement.innerHTML = text;
|
1212
|
+
for (var j = 1; j < line.height; ++j) {
|
1213
|
+
markerElement.appendChild(elt("br"));
|
1214
|
+
markerElement.appendChild(document.createTextNode("\u00a0"));
|
1215
|
+
}
|
1244
1216
|
if (!marker) normalNode = i;
|
1245
1217
|
}
|
1246
1218
|
++i;
|
1247
1219
|
});
|
1248
1220
|
gutter.style.display = "none";
|
1249
|
-
gutterText
|
1221
|
+
removeChildrenAndAdd(gutterText, fragment);
|
1250
1222
|
// Make sure scrolling doesn't cause number gutter size to pop
|
1251
1223
|
if (normalNode != null && options.lineNumbers) {
|
1252
1224
|
var node = gutterText.childNodes[normalNode - showingFrom];
|
@@ -1274,15 +1246,15 @@ var CodeMirror = (function() {
|
|
1274
1246
|
cursor.style.display = "";
|
1275
1247
|
selectionDiv.style.display = "none";
|
1276
1248
|
} else {
|
1277
|
-
var sameLine = fromPos.y == toPos.y,
|
1249
|
+
var sameLine = fromPos.y == toPos.y, fragment = document.createDocumentFragment();
|
1278
1250
|
var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
|
1279
1251
|
var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
|
1280
|
-
|
1252
|
+
var add = function(left, top, right, height) {
|
1281
1253
|
var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px"
|
1282
1254
|
: "right: " + right + "px";
|
1283
|
-
|
1284
|
-
|
1285
|
-
}
|
1255
|
+
fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
|
1256
|
+
"px; top: " + top + "px; " + rstyle + "; height: " + height + "px"));
|
1257
|
+
};
|
1286
1258
|
if (sel.from.ch && fromPos.y >= 0) {
|
1287
1259
|
var right = sameLine ? clientWidth - toPos.x : 0;
|
1288
1260
|
add(fromPos.x, fromPos.y, right, th);
|
@@ -1293,7 +1265,7 @@ var CodeMirror = (function() {
|
|
1293
1265
|
add(0, middleStart, 0, middleHeight);
|
1294
1266
|
if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)
|
1295
1267
|
add(0, toPos.y, clientWidth - toPos.x, th);
|
1296
|
-
selectionDiv
|
1268
|
+
removeChildrenAndAdd(selectionDiv, fragment);
|
1297
1269
|
cursor.style.display = "none";
|
1298
1270
|
selectionDiv.style.display = "";
|
1299
1271
|
}
|
@@ -1425,13 +1397,16 @@ var CodeMirror = (function() {
|
|
1425
1397
|
else replaceRange("", sel.from, findPosH(dir, unit));
|
1426
1398
|
userSelChange = true;
|
1427
1399
|
}
|
1428
|
-
var goalColumn = null;
|
1429
1400
|
function moveV(dir, unit) {
|
1430
1401
|
var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);
|
1431
1402
|
if (goalColumn != null) pos.x = goalColumn;
|
1432
|
-
if (unit == "page")
|
1433
|
-
|
1434
|
-
|
1403
|
+
if (unit == "page") {
|
1404
|
+
var screen = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);
|
1405
|
+
var target = coordsChar(pos.x, pos.y + screen * dir);
|
1406
|
+
} else if (unit == "line") {
|
1407
|
+
var th = textHeight();
|
1408
|
+
var target = coordsChar(pos.x, pos.y + .5 * th + dir * th);
|
1409
|
+
}
|
1435
1410
|
if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y;
|
1436
1411
|
setCursor(target.line, target.ch, true);
|
1437
1412
|
goalColumn = pos.x;
|
@@ -1440,10 +1415,15 @@ var CodeMirror = (function() {
|
|
1440
1415
|
function findWordAt(pos) {
|
1441
1416
|
var line = getLine(pos.line).text;
|
1442
1417
|
var start = pos.ch, end = pos.ch;
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1418
|
+
if (line) {
|
1419
|
+
if (pos.after === false || end == line.length) --start; else ++end;
|
1420
|
+
var startChar = line.charAt(start);
|
1421
|
+
var check = isWordChar(startChar) ? isWordChar :
|
1422
|
+
/\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} :
|
1423
|
+
function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
|
1424
|
+
while (start > 0 && check(line.charAt(start - 1))) --start;
|
1425
|
+
while (end < line.length && check(line.charAt(end))) ++end;
|
1426
|
+
}
|
1447
1427
|
return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}};
|
1448
1428
|
}
|
1449
1429
|
function selectLine(line) {
|
@@ -1482,7 +1462,8 @@ var CodeMirror = (function() {
|
|
1482
1462
|
for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";}
|
1483
1463
|
while (pos < indentation) {++pos; indentString += " ";}
|
1484
1464
|
|
1485
|
-
|
1465
|
+
if (indentString != curSpaceString)
|
1466
|
+
replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});
|
1486
1467
|
}
|
1487
1468
|
|
1488
1469
|
function loadMode() {
|
@@ -1506,14 +1487,12 @@ var CodeMirror = (function() {
|
|
1506
1487
|
var guess = Math.ceil(line.text.length / perLine) || 1;
|
1507
1488
|
if (guess != 1) updateLineHeight(line, guess);
|
1508
1489
|
});
|
1509
|
-
lineSpace.style.
|
1510
|
-
widthForcer.style.left = "";
|
1490
|
+
lineSpace.style.minWidth = widthForcer.style.left = "";
|
1511
1491
|
} else {
|
1512
1492
|
wrapper.className = wrapper.className.replace(" CodeMirror-wrap", "");
|
1513
|
-
|
1493
|
+
computeMaxLength();
|
1514
1494
|
doc.iter(0, doc.size, function(line) {
|
1515
1495
|
if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);
|
1516
|
-
if (line.text.length > maxLine.length) maxLine = line.text;
|
1517
1496
|
});
|
1518
1497
|
}
|
1519
1498
|
changes.push({from: 0, to: doc.size});
|
@@ -1521,8 +1500,9 @@ var CodeMirror = (function() {
|
|
1521
1500
|
function makeTab(col) {
|
1522
1501
|
var w = options.tabSize - col % options.tabSize, cached = tabCache[w];
|
1523
1502
|
if (cached) return cached;
|
1524
|
-
for (var str =
|
1525
|
-
|
1503
|
+
for (var str = "", i = 0; i < w; ++i) str += " ";
|
1504
|
+
var span = elt("span", str, "cm-tab");
|
1505
|
+
return (tabCache[w] = {element: span, width: w});
|
1526
1506
|
}
|
1527
1507
|
function themeChanged() {
|
1528
1508
|
scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
|
@@ -1641,11 +1621,10 @@ var CodeMirror = (function() {
|
|
1641
1621
|
if (line.hidden != hidden) {
|
1642
1622
|
line.hidden = hidden;
|
1643
1623
|
if (!options.lineWrapping) {
|
1644
|
-
|
1645
|
-
if (hidden && l.length == maxLine.length) {
|
1624
|
+
if (hidden && line.text.length == maxLine.text.length) {
|
1646
1625
|
updateMaxLine = true;
|
1647
|
-
} else if (!hidden &&
|
1648
|
-
maxLine =
|
1626
|
+
} else if (!hidden && line.text.length > maxLine.text.length) {
|
1627
|
+
maxLine = line; updateMaxLine = false;
|
1649
1628
|
}
|
1650
1629
|
}
|
1651
1630
|
updateLineHeight(line, hidden ? 0 : 1);
|
@@ -1677,11 +1656,6 @@ var CodeMirror = (function() {
|
|
1677
1656
|
markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};
|
1678
1657
|
}
|
1679
1658
|
|
1680
|
-
function stringWidth(str) {
|
1681
|
-
measure.innerHTML = "<pre><span>x</span></pre>";
|
1682
|
-
measure.firstChild.firstChild.firstChild.nodeValue = str;
|
1683
|
-
return measure.firstChild.firstChild.offsetWidth || 10;
|
1684
|
-
}
|
1685
1659
|
// These are used to go from pixel positions to character
|
1686
1660
|
// positions, taking varying character widths into account.
|
1687
1661
|
function charFromX(line, x) {
|
@@ -1711,19 +1685,18 @@ var CodeMirror = (function() {
|
|
1711
1685
|
}
|
1712
1686
|
}
|
1713
1687
|
|
1714
|
-
var tempId = "CodeMirror-temp-" + Math.floor(Math.random() * 0xffffff).toString(16);
|
1715
1688
|
function measureLine(line, ch) {
|
1716
1689
|
if (ch == 0) return {top: 0, left: 0};
|
1717
1690
|
var wbr = options.lineWrapping && ch < line.text.length &&
|
1718
1691
|
spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
|
1719
|
-
|
1720
|
-
|
1721
|
-
var
|
1692
|
+
var pre = line.getElement(makeTab, ch, wbr);
|
1693
|
+
removeChildrenAndAdd(measure, pre);
|
1694
|
+
var anchor = pre.anchor;
|
1695
|
+
var top = anchor.offsetTop, left = anchor.offsetLeft;
|
1722
1696
|
// Older IEs report zero offsets for spans directly after a wrap
|
1723
1697
|
if (ie && top == 0 && left == 0) {
|
1724
|
-
var backup =
|
1725
|
-
backup.
|
1726
|
-
elt.parentNode.insertBefore(backup, elt.nextSibling);
|
1698
|
+
var backup = elt("span", "x");
|
1699
|
+
anchor.parentNode.insertBefore(backup, anchor.nextSibling);
|
1727
1700
|
top = backup.offsetTop;
|
1728
1701
|
}
|
1729
1702
|
return {top: top, left: left};
|
@@ -1740,17 +1713,19 @@ var CodeMirror = (function() {
|
|
1740
1713
|
}
|
1741
1714
|
// Coords must be lineSpace-local
|
1742
1715
|
function coordsChar(x, y) {
|
1743
|
-
if (y < 0) y = 0;
|
1744
1716
|
var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);
|
1717
|
+
if (heightPos < 0) return {line: 0, ch: 0};
|
1745
1718
|
var lineNo = lineAtHeight(doc, heightPos);
|
1746
1719
|
if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length};
|
1747
1720
|
var lineObj = getLine(lineNo), text = lineObj.text;
|
1748
1721
|
var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;
|
1749
1722
|
if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};
|
1723
|
+
var wrongLine = false;
|
1750
1724
|
function getX(len) {
|
1751
1725
|
var sp = measureLine(lineObj, len);
|
1752
1726
|
if (tw) {
|
1753
1727
|
var off = Math.round(sp.top / th);
|
1728
|
+
wrongLine = off != innerOff;
|
1754
1729
|
return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);
|
1755
1730
|
}
|
1756
1731
|
return sp.left;
|
@@ -1769,9 +1744,12 @@ var CodeMirror = (function() {
|
|
1769
1744
|
if (estX < x) {from = estimated; fromX = estX;}
|
1770
1745
|
// Do a binary search between these bounds.
|
1771
1746
|
for (;;) {
|
1772
|
-
if (to - from <= 1)
|
1747
|
+
if (to - from <= 1) {
|
1748
|
+
var after = x - fromX < toX - x;
|
1749
|
+
return {line: lineNo, ch: after ? from : to, after: after};
|
1750
|
+
}
|
1773
1751
|
var middle = Math.ceil((from + to) / 2), middleX = getX(middle);
|
1774
|
-
if (middleX > x) {to = middle; toX = middleX;}
|
1752
|
+
if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; }
|
1775
1753
|
else {from = middle; fromX = middleX;}
|
1776
1754
|
}
|
1777
1755
|
}
|
@@ -1780,26 +1758,32 @@ var CodeMirror = (function() {
|
|
1780
1758
|
return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};
|
1781
1759
|
}
|
1782
1760
|
|
1783
|
-
var cachedHeight, cachedHeightFor,
|
1761
|
+
var cachedHeight, cachedHeightFor, measurePre;
|
1784
1762
|
function textHeight() {
|
1785
|
-
if (
|
1786
|
-
|
1787
|
-
for (var i = 0; i < 49; ++i)
|
1788
|
-
|
1763
|
+
if (measurePre == null) {
|
1764
|
+
measurePre = elt("pre");
|
1765
|
+
for (var i = 0; i < 49; ++i) {
|
1766
|
+
measurePre.appendChild(document.createTextNode("x"));
|
1767
|
+
measurePre.appendChild(elt("br"));
|
1768
|
+
}
|
1769
|
+
measurePre.appendChild(document.createTextNode("x"));
|
1789
1770
|
}
|
1790
1771
|
var offsetHeight = lineDiv.clientHeight;
|
1791
1772
|
if (offsetHeight == cachedHeightFor) return cachedHeight;
|
1792
1773
|
cachedHeightFor = offsetHeight;
|
1793
|
-
measure.
|
1774
|
+
removeChildrenAndAdd(measure, measurePre.cloneNode(true));
|
1794
1775
|
cachedHeight = measure.firstChild.offsetHeight / 50 || 1;
|
1795
|
-
measure
|
1776
|
+
removeChildren(measure);
|
1796
1777
|
return cachedHeight;
|
1797
1778
|
}
|
1798
1779
|
var cachedWidth, cachedWidthFor = 0;
|
1799
1780
|
function charWidth() {
|
1800
1781
|
if (scroller.clientWidth == cachedWidthFor) return cachedWidth;
|
1801
1782
|
cachedWidthFor = scroller.clientWidth;
|
1802
|
-
|
1783
|
+
var anchor = elt("span", "x");
|
1784
|
+
var pre = elt("pre", [anchor]);
|
1785
|
+
removeChildrenAndAdd(measure, pre);
|
1786
|
+
return (cachedWidth = anchor.offsetWidth || 10);
|
1803
1787
|
}
|
1804
1788
|
function paddingTop() {return lineSpace.offsetTop;}
|
1805
1789
|
function paddingLeft() {return lineSpace.offsetLeft;}
|
@@ -1860,7 +1844,7 @@ var CodeMirror = (function() {
|
|
1860
1844
|
cursor.style.visibility = "";
|
1861
1845
|
blinker = setInterval(function() {
|
1862
1846
|
cursor.style.visibility = (on = !on) ? "" : "hidden";
|
1863
|
-
},
|
1847
|
+
}, options.cursorBlinkRate);
|
1864
1848
|
}
|
1865
1849
|
|
1866
1850
|
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
|
@@ -2000,9 +1984,11 @@ var CodeMirror = (function() {
|
|
2000
1984
|
function endOperation() {
|
2001
1985
|
if (updateMaxLine) computeMaxLength();
|
2002
1986
|
if (maxLineChanged && !options.lineWrapping) {
|
2003
|
-
var cursorWidth = widthForcer.offsetWidth, left =
|
2004
|
-
|
2005
|
-
|
1987
|
+
var cursorWidth = widthForcer.offsetWidth, left = measureLine(maxLine, maxLine.text.length).left;
|
1988
|
+
if (!ie_lt8) {
|
1989
|
+
widthForcer.style.left = left + "px";
|
1990
|
+
lineSpace.style.minWidth = (left + cursorWidth) + "px";
|
1991
|
+
}
|
2006
1992
|
maxLineChanged = false;
|
2007
1993
|
}
|
2008
1994
|
var newScrollPos, updated;
|
@@ -2010,13 +1996,14 @@ var CodeMirror = (function() {
|
|
2010
1996
|
var coords = calculateCursorCoords();
|
2011
1997
|
newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot);
|
2012
1998
|
}
|
2013
|
-
if (changes.length
|
2014
|
-
|
1999
|
+
if (changes.length || newScrollPos && newScrollPos.scrollTop != null)
|
2000
|
+
updated = updateDisplay(changes, true, newScrollPos && newScrollPos.scrollTop);
|
2001
|
+
if (!updated) {
|
2015
2002
|
if (selectionChanged) updateSelection();
|
2016
2003
|
if (gutterDirty) updateGutter();
|
2017
2004
|
}
|
2018
2005
|
if (newScrollPos) scrollCursorIntoView();
|
2019
|
-
if (selectionChanged)
|
2006
|
+
if (selectionChanged) restartBlink();
|
2020
2007
|
|
2021
2008
|
if (focused && !leaveInputAlone &&
|
2022
2009
|
(updateInput === true || (updateInput !== false && selectionChanged)))
|
@@ -2081,11 +2068,13 @@ var CodeMirror = (function() {
|
|
2081
2068
|
dragDrop: true,
|
2082
2069
|
onChange: null,
|
2083
2070
|
onCursorActivity: null,
|
2071
|
+
onViewportChange: null,
|
2084
2072
|
onGutterClick: null,
|
2085
2073
|
onHighlightComplete: null,
|
2086
2074
|
onUpdate: null,
|
2087
2075
|
onFocus: null, onBlur: null, onScroll: null,
|
2088
2076
|
matchBrackets: false,
|
2077
|
+
cursorBlinkRate: 530,
|
2089
2078
|
workTime: 100,
|
2090
2079
|
workDelay: 200,
|
2091
2080
|
pollInterval: 100,
|
@@ -2241,6 +2230,10 @@ var CodeMirror = (function() {
|
|
2241
2230
|
function lookup(map) {
|
2242
2231
|
map = getKeyMap(map);
|
2243
2232
|
var found = map[name];
|
2233
|
+
if (found === false) {
|
2234
|
+
if (stop) stop();
|
2235
|
+
return true;
|
2236
|
+
}
|
2244
2237
|
if (found != null && handle(found)) return true;
|
2245
2238
|
if (map.nofallthrough) {
|
2246
2239
|
if (stop) stop();
|
@@ -2268,8 +2261,15 @@ var CodeMirror = (function() {
|
|
2268
2261
|
options.value = textarea.value;
|
2269
2262
|
if (!options.tabindex && textarea.tabindex)
|
2270
2263
|
options.tabindex = textarea.tabindex;
|
2271
|
-
|
2272
|
-
|
2264
|
+
// Set autofocus to true if this textarea is focused, or if it has
|
2265
|
+
// autofocus and no other element is focused.
|
2266
|
+
if (options.autofocus == null) {
|
2267
|
+
var hasFocus = document.body;
|
2268
|
+
// doc.activeElement occasionally throws on IE
|
2269
|
+
try { hasFocus = document.activeElement; } catch(e) {}
|
2270
|
+
options.autofocus = hasFocus == textarea ||
|
2271
|
+
textarea.getAttribute("autofocus") != null && hasFocus == document.body;
|
2272
|
+
}
|
2273
2273
|
|
2274
2274
|
function save() {textarea.value = instance.getValue();}
|
2275
2275
|
if (textarea.form) {
|
@@ -2277,13 +2277,12 @@ var CodeMirror = (function() {
|
|
2277
2277
|
var rmSubmit = connect(textarea.form, "submit", save, true);
|
2278
2278
|
if (typeof textarea.form.submit == "function") {
|
2279
2279
|
var realSubmit = textarea.form.submit;
|
2280
|
-
function wrappedSubmit() {
|
2280
|
+
textarea.form.submit = function wrappedSubmit() {
|
2281
2281
|
save();
|
2282
2282
|
textarea.form.submit = realSubmit;
|
2283
2283
|
textarea.form.submit();
|
2284
2284
|
textarea.form.submit = wrappedSubmit;
|
2285
|
-
}
|
2286
|
-
textarea.form.submit = wrappedSubmit;
|
2285
|
+
};
|
2287
2286
|
}
|
2288
2287
|
}
|
2289
2288
|
|
@@ -2306,6 +2305,18 @@ var CodeMirror = (function() {
|
|
2306
2305
|
return instance;
|
2307
2306
|
};
|
2308
2307
|
|
2308
|
+
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
|
2309
|
+
var ie = /MSIE \d/.test(navigator.userAgent);
|
2310
|
+
var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
|
2311
|
+
var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
|
2312
|
+
var quirksMode = ie && document.documentMode == 5;
|
2313
|
+
var webkit = /WebKit\//.test(navigator.userAgent);
|
2314
|
+
var chrome = /Chrome\//.test(navigator.userAgent);
|
2315
|
+
var opera = /Opera\//.test(navigator.userAgent);
|
2316
|
+
var safari = /Apple Computer/.test(navigator.vendor);
|
2317
|
+
var khtml = /KHTML\//.test(navigator.userAgent);
|
2318
|
+
var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);
|
2319
|
+
|
2309
2320
|
// Utility functions for working with state. Exported because modes
|
2310
2321
|
// sometimes need to do this.
|
2311
2322
|
function copyState(mode, state) {
|
@@ -2334,7 +2345,7 @@ var CodeMirror = (function() {
|
|
2334
2345
|
StringStream.prototype = {
|
2335
2346
|
eol: function() {return this.pos >= this.string.length;},
|
2336
2347
|
sol: function() {return this.pos == 0;},
|
2337
|
-
peek: function() {return this.string.charAt(this.pos);},
|
2348
|
+
peek: function() {return this.string.charAt(this.pos) || undefined;},
|
2338
2349
|
next: function() {
|
2339
2350
|
if (this.pos < this.string.length)
|
2340
2351
|
return this.string.charAt(this.pos++);
|
@@ -2365,7 +2376,7 @@ var CodeMirror = (function() {
|
|
2365
2376
|
indentation: function() {return countColumn(this.string, null, this.tabSize);},
|
2366
2377
|
match: function(pattern, consume, caseInsensitive) {
|
2367
2378
|
if (typeof pattern == "string") {
|
2368
|
-
|
2379
|
+
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
2369
2380
|
if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
|
2370
2381
|
if (consume !== false) this.pos += pattern.length;
|
2371
2382
|
return true;
|
@@ -2444,14 +2455,22 @@ var CodeMirror = (function() {
|
|
2444
2455
|
}
|
2445
2456
|
};
|
2446
2457
|
|
2458
|
+
// When measuring the position of the end of a line, different
|
2459
|
+
// browsers require different approaches. If an empty span is added,
|
2460
|
+
// many browsers report bogus offsets. Of those, some (Webkit,
|
2461
|
+
// recent IE) will accept a space without moving the whole span to
|
2462
|
+
// the next line when wrapping it, others work with a zero-width
|
2463
|
+
// space.
|
2464
|
+
var eolSpanContent = " ";
|
2465
|
+
if (gecko || (ie && !ie_lt8)) eolSpanContent = "\u200b";
|
2466
|
+
else if (opera) eolSpanContent = "";
|
2467
|
+
|
2447
2468
|
// Line objects. These hold state related to a line, including
|
2448
2469
|
// highlighting info (the styles array).
|
2449
2470
|
function Line(text, styles) {
|
2450
2471
|
this.styles = styles || [text, null];
|
2451
2472
|
this.text = text;
|
2452
2473
|
this.height = 1;
|
2453
|
-
this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;
|
2454
|
-
this.stateAfter = this.parent = this.hidden = null;
|
2455
2474
|
}
|
2456
2475
|
Line.inheritMarks = function(text, orig) {
|
2457
2476
|
var ln = new Line(text), mk = orig && orig.marked;
|
@@ -2464,7 +2483,7 @@ var CodeMirror = (function() {
|
|
2464
2483
|
}
|
2465
2484
|
}
|
2466
2485
|
return ln;
|
2467
|
-
}
|
2486
|
+
};
|
2468
2487
|
Line.prototype = {
|
2469
2488
|
// Replace a piece of a line, keeping the styles around it intact.
|
2470
2489
|
replace: function(from, to_, text) {
|
@@ -2542,7 +2561,7 @@ var CodeMirror = (function() {
|
|
2542
2561
|
if (close && omk) {
|
2543
2562
|
for (var j = 0; j < omk.length; ++j) {
|
2544
2563
|
var om = omk[j];
|
2545
|
-
if (!om.sameSet(mark) || om.from != null) continue
|
2564
|
+
if (!om.sameSet(mark) || om.from != null) continue;
|
2546
2565
|
if (mark.from == this.text.length && om.to == 0) {
|
2547
2566
|
omk.splice(j, 1);
|
2548
2567
|
mk.splice(i--, 1);
|
@@ -2600,8 +2619,8 @@ var CodeMirror = (function() {
|
|
2600
2619
|
},
|
2601
2620
|
// Fetch the parser token for a given character. Useful for hacks
|
2602
2621
|
// that want to inspect the mode state (say, for completion).
|
2603
|
-
getTokenAt: function(mode, state, ch) {
|
2604
|
-
var txt = this.text, stream = new StringStream(txt);
|
2622
|
+
getTokenAt: function(mode, state, tabSize, ch) {
|
2623
|
+
var txt = this.text, stream = new StringStream(txt, tabSize);
|
2605
2624
|
while (stream.pos < ch && !stream.eol()) {
|
2606
2625
|
stream.start = stream.pos;
|
2607
2626
|
var style = mode.token(stream, state);
|
@@ -2615,68 +2634,72 @@ var CodeMirror = (function() {
|
|
2615
2634
|
indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
|
2616
2635
|
// Produces an HTML fragment for the line, taking selection,
|
2617
2636
|
// marking, and highlighting into account.
|
2618
|
-
|
2619
|
-
var
|
2620
|
-
|
2637
|
+
getElement: function(makeTab, wrapAt, wrapWBR) {
|
2638
|
+
var first = true, col = 0, specials = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g;
|
2639
|
+
var pre = elt("pre");
|
2640
|
+
function span_(html, text, style) {
|
2621
2641
|
if (!text) return;
|
2622
2642
|
// Work around a bug where, in some compat modes, IE ignores leading spaces
|
2623
2643
|
if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
|
2624
2644
|
first = false;
|
2625
|
-
if (
|
2645
|
+
if (!specials.test(text)) {
|
2626
2646
|
col += text.length;
|
2627
|
-
var
|
2647
|
+
var content = document.createTextNode(text);
|
2628
2648
|
} else {
|
2629
|
-
var
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2636
|
-
|
2637
|
-
|
2649
|
+
var content = document.createDocumentFragment(), pos = 0;
|
2650
|
+
while (true) {
|
2651
|
+
specials.lastIndex = pos;
|
2652
|
+
var m = specials.exec(text);
|
2653
|
+
var skipped = m ? m.index - pos : text.length - pos;
|
2654
|
+
if (skipped) {
|
2655
|
+
content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
|
2656
|
+
col += skipped;
|
2657
|
+
}
|
2658
|
+
if (!m) break;
|
2659
|
+
pos += skipped + 1;
|
2660
|
+
if (m[0] == "\t") {
|
2638
2661
|
var tab = makeTab(col);
|
2639
|
-
|
2662
|
+
content.appendChild(tab.element.cloneNode(true));
|
2640
2663
|
col += tab.width;
|
2641
|
-
|
2664
|
+
} else {
|
2665
|
+
var token = elt("span", "\u2022", "cm-invalidchar");
|
2666
|
+
token.title = "\\u" + m[0].charCodeAt(0).toString(16);
|
2667
|
+
content.appendChild(token);
|
2668
|
+
col += 1;
|
2642
2669
|
}
|
2643
2670
|
}
|
2644
2671
|
}
|
2645
|
-
if (style) html.
|
2646
|
-
else html.
|
2672
|
+
if (style) html.appendChild(elt("span", [content], style));
|
2673
|
+
else html.appendChild(content);
|
2647
2674
|
}
|
2648
2675
|
var span = span_;
|
2649
2676
|
if (wrapAt != null) {
|
2650
|
-
var outPos = 0,
|
2651
|
-
span = function(text, style) {
|
2677
|
+
var outPos = 0, anchor = pre.anchor = elt("span");
|
2678
|
+
span = function(html, text, style) {
|
2652
2679
|
var l = text.length;
|
2653
2680
|
if (wrapAt >= outPos && wrapAt < outPos + l) {
|
2654
2681
|
if (wrapAt > outPos) {
|
2655
|
-
span_(text.slice(0, wrapAt - outPos), style);
|
2682
|
+
span_(html, text.slice(0, wrapAt - outPos), style);
|
2656
2683
|
// See comment at the definition of spanAffectsWrapping
|
2657
|
-
if (wrapWBR) html.
|
2684
|
+
if (wrapWBR) html.appendChild(elt("wbr"));
|
2658
2685
|
}
|
2659
|
-
html.
|
2686
|
+
html.appendChild(anchor);
|
2660
2687
|
var cut = wrapAt - outPos;
|
2661
|
-
span_(opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
|
2662
|
-
html.
|
2663
|
-
if (opera) span_(text.slice(cut + 1), style);
|
2688
|
+
span_(anchor, opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
|
2689
|
+
if (opera) span_(html, text.slice(cut + 1), style);
|
2664
2690
|
wrapAt--;
|
2665
2691
|
outPos += l;
|
2666
2692
|
} else {
|
2667
2693
|
outPos += l;
|
2668
|
-
span_(text, style);
|
2669
|
-
|
2670
|
-
|
2671
|
-
|
2672
|
-
|
2673
|
-
// to determine which to use.)
|
2674
|
-
if (outPos == wrapAt && outPos == len)
|
2675
|
-
html.push(open + (gecko || (ie && !ie_lt8) ? "​" : " ") + "</span>");
|
2694
|
+
span_(html, text, style);
|
2695
|
+
if (outPos == wrapAt && outPos == len) {
|
2696
|
+
setTextContent(anchor, eolSpanContent);
|
2697
|
+
html.appendChild(anchor);
|
2698
|
+
}
|
2676
2699
|
// Stop outputting HTML when gone sufficiently far beyond measure
|
2677
2700
|
else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
|
2678
2701
|
}
|
2679
|
-
}
|
2702
|
+
};
|
2680
2703
|
}
|
2681
2704
|
|
2682
2705
|
var st = this.styles, allText = this.text, marked = this.marked;
|
@@ -2685,20 +2708,19 @@ var CodeMirror = (function() {
|
|
2685
2708
|
if (!style) return null;
|
2686
2709
|
return "cm-" + style.replace(/ +/g, " cm-");
|
2687
2710
|
}
|
2688
|
-
|
2689
2711
|
if (!allText && wrapAt == null) {
|
2690
|
-
span(" ");
|
2712
|
+
span(pre, " ");
|
2691
2713
|
} else if (!marked || !marked.length) {
|
2692
2714
|
for (var i = 0, ch = 0; ch < len; i+=2) {
|
2693
2715
|
var str = st[i], style = st[i+1], l = str.length;
|
2694
2716
|
if (ch + l > len) str = str.slice(0, len - ch);
|
2695
2717
|
ch += l;
|
2696
|
-
span(str, styleToClass(style));
|
2718
|
+
span(pre, str, styleToClass(style));
|
2697
2719
|
}
|
2698
2720
|
} else {
|
2699
2721
|
var pos = 0, i = 0, text = "", style, sg = 0;
|
2700
2722
|
var nextChange = marked[0].from || 0, marks = [], markpos = 0;
|
2701
|
-
|
2723
|
+
var advanceMarks = function() {
|
2702
2724
|
var m;
|
2703
2725
|
while (markpos < marked.length &&
|
2704
2726
|
((m = marked[markpos]).from == pos || m.from == null)) {
|
@@ -2712,7 +2734,7 @@ var CodeMirror = (function() {
|
|
2712
2734
|
if (to == pos) marks.splice(i--, 1);
|
2713
2735
|
else nextChange = Math.min(to, nextChange);
|
2714
2736
|
}
|
2715
|
-
}
|
2737
|
+
};
|
2716
2738
|
var m = 0;
|
2717
2739
|
while (pos < len) {
|
2718
2740
|
if (nextChange == pos) advanceMarks();
|
@@ -2723,7 +2745,7 @@ var CodeMirror = (function() {
|
|
2723
2745
|
var appliedStyle = style;
|
2724
2746
|
for (var j = 0; j < marks.length; ++j)
|
2725
2747
|
appliedStyle = (appliedStyle ? appliedStyle + " " : "") + marks[j].style;
|
2726
|
-
span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
|
2748
|
+
span(pre, end > upto ? text.slice(0, upto - pos) : text, appliedStyle);
|
2727
2749
|
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
|
2728
2750
|
pos = end;
|
2729
2751
|
}
|
@@ -2731,7 +2753,7 @@ var CodeMirror = (function() {
|
|
2731
2753
|
}
|
2732
2754
|
}
|
2733
2755
|
}
|
2734
|
-
return
|
2756
|
+
return pre;
|
2735
2757
|
},
|
2736
2758
|
cleanUp: function() {
|
2737
2759
|
this.parent = null;
|
@@ -3038,30 +3060,18 @@ var CodeMirror = (function() {
|
|
3038
3060
|
|
3039
3061
|
var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
|
3040
3062
|
|
3041
|
-
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
|
3042
|
-
var ie = /MSIE \d/.test(navigator.userAgent);
|
3043
|
-
var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
|
3044
|
-
var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
|
3045
|
-
var quirksMode = ie && document.documentMode == 5;
|
3046
|
-
var webkit = /WebKit\//.test(navigator.userAgent);
|
3047
|
-
var chrome = /Chrome\//.test(navigator.userAgent);
|
3048
|
-
var opera = /Opera\//.test(navigator.userAgent);
|
3049
|
-
var safari = /Apple Computer/.test(navigator.vendor);
|
3050
|
-
var khtml = /KHTML\//.test(navigator.userAgent);
|
3051
|
-
var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent);
|
3052
|
-
|
3053
3063
|
// Detect drag-and-drop
|
3054
3064
|
var dragAndDrop = function() {
|
3055
3065
|
// There is *some* kind of drag-and-drop support in IE6-8, but I
|
3056
3066
|
// couldn't get it to work yet.
|
3057
3067
|
if (ie_lt9) return false;
|
3058
|
-
var div =
|
3068
|
+
var div = elt('div');
|
3059
3069
|
return "draggable" in div || "dragDrop" in div;
|
3060
3070
|
}();
|
3061
3071
|
|
3062
3072
|
// Feature-detect whether newlines in textareas are converted to \r\n
|
3063
3073
|
var lineSep = function () {
|
3064
|
-
var te =
|
3074
|
+
var te = elt("textarea");
|
3065
3075
|
te.value = "foo\nbar";
|
3066
3076
|
if (te.value.indexOf("\r") > -1) return "\r\n";
|
3067
3077
|
return "\n";
|
@@ -3093,11 +3103,6 @@ var CodeMirror = (function() {
|
|
3093
3103
|
return n;
|
3094
3104
|
}
|
3095
3105
|
|
3096
|
-
function computedStyle(elt) {
|
3097
|
-
if (elt.currentStyle) return elt.currentStyle;
|
3098
|
-
return window.getComputedStyle(elt, null);
|
3099
|
-
}
|
3100
|
-
|
3101
3106
|
function eltOffset(node, screen) {
|
3102
3107
|
// Take the parts of bounding client rect that we are interested in so we are able to edit if need be,
|
3103
3108
|
// since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)
|
@@ -3132,27 +3137,28 @@ var CodeMirror = (function() {
|
|
3132
3137
|
function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
|
3133
3138
|
function copyPos(x) {return {line: x.line, ch: x.ch};}
|
3134
3139
|
|
3135
|
-
|
3136
|
-
|
3137
|
-
|
3138
|
-
|
3140
|
+
function elt(tag, content, className, style) {
|
3141
|
+
var e = document.createElement(tag);
|
3142
|
+
if (className) e.className = className;
|
3143
|
+
if (style) e.style.cssText = style;
|
3144
|
+
if (typeof content == "string") setTextContent(e, content);
|
3145
|
+
else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
|
3146
|
+
return e;
|
3139
3147
|
}
|
3140
|
-
|
3141
|
-
|
3142
|
-
|
3143
|
-
|
3144
|
-
|
3145
|
-
|
3146
|
-
|
3147
|
-
|
3148
|
-
|
3149
|
-
|
3150
|
-
|
3151
|
-
|
3152
|
-
return escapeElement.innerHTML;
|
3153
|
-
};
|
3148
|
+
function removeChildren(e) {
|
3149
|
+
e.innerHTML = "";
|
3150
|
+
return e;
|
3151
|
+
}
|
3152
|
+
function removeChildrenAndAdd(parent, e) {
|
3153
|
+
removeChildren(parent).appendChild(e);
|
3154
|
+
}
|
3155
|
+
function setTextContent(e, str) {
|
3156
|
+
if (ie_lt9) {
|
3157
|
+
e.innerHTML = "";
|
3158
|
+
e.appendChild(document.createTextNode(str));
|
3159
|
+
} else e.textContent = str;
|
3154
3160
|
}
|
3155
|
-
CodeMirror.
|
3161
|
+
CodeMirror.setTextContent = setTextContent;
|
3156
3162
|
|
3157
3163
|
// Used to position the cursor after an undo/redo by finding the
|
3158
3164
|
// last edited character.
|