codemirror-rails 2.32 → 2.33
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/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.
|