Permalink
Browse files

latest CM2 merges

  • Loading branch information...
1 parent 81c7c46 commit 3a984637b4343b0948fdc68beb64b36f6b5a227d @mzero committed Feb 18, 2011
Showing with 89 additions and 80 deletions.
  1. +4 −5 seed/static/codemirror.css
  2. +85 −75 seed/static/codemirror.js
@@ -1,5 +1,4 @@
.CodeMirror {
- position: relative;
line-height: 1em;
font-family: monospace;
x-background: #fff !important;
@@ -9,19 +8,19 @@
.CodeMirror-gutter {
position: absolute; left: 0; top: 0;
background-color: #f7f7f7;
+ min-width: 3em;
+ height: 100%;
+}
+.CodeMirror-gutter-text {
border-right: 1px solid #eee;
color: #aaa;
text-align: right;
- min-width: 3em;
padding: .5em .25em .5em .5em;
}
.CodeMirror-lines {
padding: .5em;
}
-.CodeMirror-lines > div {
- position: relative;
-}
.CodeMirror pre {
margin: 0; padding: 0;
font-family: inherit;
View
@@ -221,22 +221,25 @@ var CodeMirror = (function() {
if (mk[i] == mark) {mk.splice(i, 1); break;}
},
highlight: function(mode, state) {
- var stream = new StringStream(this.text), st = this.styles;
- st.length = 0;
+ var stream = new StringStream(this.text), st = this.styles, pos = 0, changed = false;
while (!stream.eol()) {
var style = mode.token(stream, state);
var substr = this.text.slice(stream.start, stream.pos);
stream.start = stream.pos;
- if (st.length && st[st.length-1] == style)
- st[st.length-2] += substr;
- else if (substr)
- this.styles.push(substr, style);
+ if (pos && st[pos-1] == style)
+ st[pos-2] += substr;
+ else if (substr) {
+ if (!changed && st[pos] != substr || st[pos+1] != style) changed = true;
+ st[pos++] = substr; st[pos++] = style;
+ }
// Give up when line is ridiculously long
if (stream.pos > 5000) {
this.styles.push(this.text.slice(stream.pos), null);
break;
}
}
+ if (st.length != pos) {st.length = pos; changed = true;}
+ return changed;
},
getTokenAt: function(mode, state, ch) {
var txt = this.text, stream = new StringStream(txt);
@@ -353,22 +356,23 @@ var CodeMirror = (function() {
div.className = "CodeMirror";
div.innerHTML =
'<div style="position: relative">' +
- '<pre style="position: absolute; visibility: hidden"><span>-</span></pre>' +
+ '<pre style="position: absolute; visibility: hidden">' +
+ '<span>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</span></pre>' +
'<div style="position: relative">' +
- '<div class="CodeMirror-gutter"></div>' +
+ '<div class="CodeMirror-gutter"><div class="CodeMirror-gutter-text"></div></div>' +
'<div style="overflow: hidden; position: absolute; width: 0">' +
'<textarea style="position: absolute; width: 10000px;"></textarea></div>' +
'<div class="CodeMirror-lines"><div style="position: relative">' +
'<pre class="CodeMirror-cursor">&nbsp;</pre>' +
'<div></div></div></div></div></div>';
if (place.appendChild) place.appendChild(div); else place(div);
var code = div.firstChild, measure = code.firstChild, mover = measure.nextSibling,
- gutter = mover.firstChild, inputDiv = gutter.nextSibling, input = inputDiv.firstChild,
+ gutter = mover.firstChild, gutterText = gutter.firstChild,
+ inputDiv = gutter.nextSibling, input = inputDiv.firstChild,
lineWrap = inputDiv.nextSibling.firstChild, cursor = lineWrap.firstChild, lineDiv = cursor.nextSibling;
// inputDiv.style.width = "30em"; inputDiv.style.height = "5em"; input.rows = 3;
if (options.tabindex != null) input.tabindex = options.tabindex;
- if (options.lineNumbers) {options.gutter = "ln";}
- if (!options.gutter) gutter.style.display = "none";
+ if (!options.gutter && !options.lineNumbers) gutter.style.display = "none";
var poll = new Delayed(), highlight = new Delayed(), blinker;
@@ -397,13 +401,15 @@ var CodeMirror = (function() {
connect(div, "paste", function(){input.focus(); fastPoll();});
connect(input, "paste", fastPoll);
- function stopScroll(e) {
- var up = e.e.detail ? e.e.detail < 0 : e.e.wheelDelta > 0;
- if (up ? div.scrollTop == 0 : div.scrollTop + div.clientHeight >= div.scrollHeight)
- e.stop();
+ if (options.blockDocumentScroll) {
+ function stopScroll(e) {
+ var up = e.e.detail ? e.e.detail < 0 : e.e.wheelDelta > 0;
+ if (up ? div.scrollTop == 0 : div.scrollTop + div.clientHeight >= div.scrollHeight)
+ e.stop();
+ }
+ connect(div, "mousewheel", stopScroll);
+ connect(div, "DOMMouseScroll", stopScroll);
}
- connect(div, "mousewheel", stopScroll);
- connect(div, "DOMMouseScroll", stopScroll);
if (document.activeElement == input) onFocus();
else onBlur();
@@ -423,15 +429,16 @@ var CodeMirror = (function() {
}
function onMouseDown(e) {
- var start = posFromMouse(e), last = start, target = e.target();
+ var start = posFromMouse(e), last = start, target = e.target(), going;
if (!start) return;
setCursor(start.line, start.ch, false);
if (e.button() != 1) return;
- if (target.parentNode == gutter) {
- if (options.onGutterClick)
- options.onGutterClick(instance, indexOf(gutter.childNodes, target) + showingFrom);
- return;
- }
+ for (var n = target; n != mover; n = n.parentNode)
+ if (n.parentNode == gutterText) {
+ if (options.onGutterClick)
+ options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom);
+ return;
+ }
if (!focused) onFocus();
e.stop();
@@ -440,19 +447,27 @@ var CodeMirror = (function() {
updateInput = true;
move(); up();
}
-
- var move = connect(document, "mousemove", operation(function(e) {
- e.stop();
- if (!e.button()) {end(); return;}
+ function extend(e) {
var cur = posFromMouse(e);
if (cur && !posEq(cur, last)) {
if (!focused) onFocus();
last = cur;
setSelection(start, cur);
updateInput = false;
+ var visible = visibleLines();
+ if (cur.line >= visible.to || cur.line < visible.from)
+ going = setTimeout(operation(function(){extend(e);}), 150);
}
+ }
+
+ var move = connect(document, "mousemove", operation(function(e) {
+ clearTimeout(going);
+ e.stop();
+ if (!e.button()) {end(); return;}
+ extend(e);
}), true);
var up = connect(document, "mouseup", operation(function(e) {
+ clearTimeout(going);
var cur = posFromMouse(e);
if (cur) setSelection(start, cur);
e.stop();
@@ -737,12 +752,14 @@ var CodeMirror = (function() {
div.scrollLeft = x2 + 10 - screenw;
}
+ function visibleLines() {
+ var lh = lineHeight(), top = div.scrollTop - paddingTop();
+ return {from: Math.max(0, Math.floor(top / lh)),
+ to: Math.min(lines.length, Math.ceil((top + div.clientHeight) / lh))};
+ }
function updateDisplay(changes) {
if (!div.clientWidth) return;
- var lh = lineHeight(), top = div.scrollTop - paddingTop();
- var visibleFrom = Math.max(0, Math.floor(top / lh));
- var visibleTo = Math.min(lines.length, Math.ceil((top + div.clientHeight) / lh));
-
+ var visible = visibleLines();
var intact = [{from: showingFrom, to: showingTo, domStart: 0}];
for (var i = 0, l = changes ? changes.length : 0; i < l; ++i) {
var change = changes[i], intact2 = [], diff = change.diff || 0;
@@ -763,8 +780,8 @@ var CodeMirror = (function() {
intact = intact2;
}
- var from = Math.min(showingFrom, Math.max(visibleFrom - 3, 0)),
- to = Math.min(lines.length, Math.max(showingTo, visibleTo + 3)),
+ var from = Math.min(showingFrom, Math.max(visible.from - 3, 0)),
+ to = Math.min(lines.length, Math.max(showingTo, visible.to + 3)),
updates = [], domPos = 0, domEnd = showingTo - showingFrom, pos = from, changedLines = 0;
for (var i = 0, l = intact.length; i < l; ++i) {
@@ -786,8 +803,8 @@ var CodeMirror = (function() {
if (!updates.length) return;
lineDiv.style.display = "none";
// TODO heuristic, do some tests
- if (changedLines > (visibleTo - visibleFrom) * .3)
- refreshDisplay(from = Math.max(visibleFrom - 10, 0), to = Math.min(visibleTo + 7, lines.length));
+ if (changedLines > (visible.to - visible.from) * .3)
+ refreshDisplay(from = Math.max(visible.from - 10, 0), to = Math.min(visible.to + 7, lines.length));
else
patchDisplay(updates);
lineDiv.style.display = "";
@@ -863,21 +880,21 @@ var CodeMirror = (function() {
}
}
function updateGutter() {
- if (!options.gutter) return;
- gutter.style.height = Math.max(lineDiv.offsetHeight, div.clientHeight) + "px";
+ if (!options.gutter && !options.lineNumbers) return;
+ gutter.style.height = Math.max(mover.offsetHeight, div.clientHeight) + "px";
var html = [];
for (var i = showingFrom; i < showingTo; ++i) {
var marker = lines[i].gutterMarker;
- var text = options.lineNumbers && i + options.firstLineNumber;
+ var text = options.lineNumbers ? i + options.firstLineNumber : null;
if (marker && marker.text)
text = marker.text.replace("%N%", text != null ? text : "");
else if (text == null)
text = "\u00a0";
html.push((marker && marker.style ? '<pre class="' + marker.style + '">' : "<pre>"), text, "</pre>");
}
gutter.style.display = "none";
- gutter.innerHTML = html.join("");
- var minwidth = String(lines.length).length, firstNode = gutter.firstChild.firstChild, val = firstNode.nodeValue;
+ gutterText.innerHTML = html.join("");
+ var minwidth = String(lines.length).length, firstNode = gutterText.firstChild.firstChild, val = firstNode.nodeValue;
while (val.length < minwidth) val = "\u00a0" + val;
firstNode.nodeValue = val;
gutter.style.display = "";
@@ -1066,25 +1083,15 @@ var CodeMirror = (function() {
}
function setMode(spec) {
- options.mode = spec;
mode = CodeMirror.getMode(options, spec);
for (var i = 0, l = lines.length; i < l; ++i)
lines[i].stateAfter = null;
work = [0];
}
- function setLineNumbers(on) {
- options.lineNumbers = on;
- if (on && !options.gutter) options.gutter = "ln";
- else if (!on && options.gutter == "ln") options.gutter = false;
- gutterChanged();
- }
- function setGutter(on) {
- options.gutter = !on && options.lineNumbers ? "ln" : !!on;
- gutterChanged();
- }
function gutterChanged() {
- gutter.style.display = options.gutter ? "" : "none";
- if (options.gutter) updateGutter();
+ var visible = options.gutter || options.lineNumbers;
+ gutter.style.display = visible ? "" : "none";
+ if (visible) updateGutter();
else lineDiv.parentNode.style.marginLeft = 0;
}
@@ -1114,12 +1121,13 @@ var CodeMirror = (function() {
}
function charX(line, pos) {
- var text = lines[line].text;
+ var text = lines[line].text, span = measure.firstChild;
if (text.lastIndexOf("\t", pos) == -1) return pos * charWidth();
+ var old = span.firstChild.nodeValue;
try {
- measure.firstChild.firstChild.nodeValue = text.slice(0, pos);
- return measure.firstChild.offsetWidth;
- } finally {measure.firstChild.firstChild.nodeValue = "-";}
+ span.firstChild.nodeValue = text.slice(0, pos);
+ return span.offsetWidth;
+ } finally {span.firstChild.nodeValue = old;}
}
function charFromX(line, x) {
var text = lines[line].text, cw = charWidth();
@@ -1150,7 +1158,7 @@ var CodeMirror = (function() {
if (nlines) return lineDiv.offsetHeight / nlines;
else return measure.offsetHeight || 1;
}
- function charWidth() {return measure.firstChild.offsetWidth || 1;}
+ function charWidth() {return (measure.firstChild.offsetWidth || 320) / 40;}
function paddingTop() {return lineWrap.offsetTop;}
function paddingLeft() {return lineWrap.offsetLeft;}
@@ -1273,23 +1281,22 @@ var CodeMirror = (function() {
while (work.length) {
if (!lines[showingFrom].stateAfter) var task = showingFrom;
else var task = work.pop()
- if (task >= lines.length || lines[task].stateAfter) continue;
+ if (task >= lines.length) continue;
var start = findStartLine(task), state = start && lines[start-1].stateAfter;
if (state) state = copyState(mode, state);
else state = mode.startState ? mode.startState() : true;
for (var i = start, l = lines.length; i < l; ++i) {
- var line = lines[i];
- // TODO don't bail out so quickly -- changes in previous lines might require a change here
- if (line.stateAfter) break;
+ var line = lines[i], hadState = line.stateAfter;
if (+new Date > end) {
work.push(i);
startWorker(options.workDelay);
changes.push({from: task, to: i});
return;
}
- line.highlight(mode, state);
+ var changed = line.highlight(mode, state);
line.stateAfter = copyState(mode, state);
+ if (hadState && !changed && line.text) break;
}
changes.push({from: task, to: i});
}
@@ -1441,15 +1448,14 @@ var CodeMirror = (function() {
replaceSelection: operation(replaceSelection),
focus: function(){input.focus(); onFocus();},
setOption: function(option, value) {
- if (option == "mode") setMode(value);
- else if (option === "lineNumbers") setLineNumbers(value);
- else if (option === "gutter") setGutter(value);
- else if (option === "indentUnit") {options.indentUnit = value; setMode(options.mode);}
- else options[option] = value;
+ options[option] = value;
+ if (option == "lineNumbers" || option == "gutter") gutterChanged();
+ else if (option == "mode") setMode(value);
},
getOption: function(option) {return options[option];},
undo: operation(undo),
redo: operation(redo),
+ historySize: function() {return {undo: history.done.length, redo: history.undone.length};},
matchBrackets: operation(function(){matchBrackets(true);}),
getTokenAt: function(pos) {
pos = clipPos(pos);
@@ -1503,6 +1509,7 @@ var CodeMirror = (function() {
enterMode: "indent",
electricChars: true,
keyHook: null,
+ blockDocumentScroll: true,
lineNumbers: false,
gutter: false,
firstLineNumber: 1,
@@ -1549,14 +1556,16 @@ var CodeMirror = (function() {
function save() {textarea.value = instance.getValue();}
if (textarea.form) {
var rmSubmit = connect(textarea.form, "submit", save, true);
- var realSubmit = textarea.form.submit;
- function wrappedSubmit() {
- save();
- textarea.form.submit = realSubmit;
- textarea.form.submit();
+ if (typeof textarea.form.submit == "function") {
+ var realSubmit = textarea.form.submit;
+ function wrappedSubmit() {
+ save();
+ textarea.form.submit = realSubmit;
+ textarea.form.submit();
+ textarea.form.submit = wrappedSubmit;
+ }
textarea.form.submit = wrappedSubmit;
}
- textarea.form.submit = wrappedSubmit;
}
textarea.style.display = "none";
@@ -1569,8 +1578,9 @@ var CodeMirror = (function() {
textarea.parentNode.removeChild(instance.getWrapperElement());
textarea.style.display = "";
if (textarea.form) {
- textarea.form.submit = realSubmit;
rmSubmit();
+ if (typeof textarea.form.submit == "function")
+ textarea.form.submit = realSubmit;
}
};
return instance;

0 comments on commit 3a98463

Please sign in to comment.