ace/Editor.js
2010-04-07 09:21:32 +02:00

503 lines
No EOL
11 KiB
JavaScript

function TextInput(parentNode, host) {
var text = document.createElement("textarea");
var style = text.style;
style.position = "absolute";
style.left = "-10000px";
style.top = "-10000px";
parentNode.appendChild(text);
var inCompostion = false;
var onTextInput = function(e) {
setTimeout(function() {
if (!inCompostion) {
if (text.value) host.onTextInput(text.value);
text.value = "";
}
}, 0)
}
var onCompositionStart = function(e)
{
inCompostion = true;
if (text.value) host.onTextInput(text.value);
text.value = "";
host.onCompositionStart();
setTimeout(onCompositionUpdate, 0);
}
var onCompositionUpdate = function() {
host.onCompositionUpdate(text.value);
}
var onCompositionEnd = function()
{
inCompostion = false;
host.onCompositionEnd();
onTextInput();
}
var onCopy = function() {
text.value = host.getCopyText();
text.select();
}
var onCut = function() {
text.value = host.getCopyText();
host.onCut();
text.select();
}
addListener(text, "keypress", onTextInput, false);
addListener(text, "textInput", onTextInput, false);
addListener(text, "paste", onTextInput, false);
addListener(text, "propertychange", onTextInput, false);
addListener(text, "copy", onCopy, false);
addListener(text, "cut", onCut, false);
addListener(text, "compositionstart", onCompositionStart, false);
addListener(text, "compositionupdate", onCompositionUpdate, false);
addListener(text, "compositionend", onCompositionEnd, false);
addListener(text, "blur", function() {
host.onBlur();
}, false);
addListener(text, "focus", function() {
host.onFocus();
}, false);
this.focus = function() {
text.focus();
}
this.blur = function() {
this.blur();
}
};
var keys = {
UP: 38,
RIGHT: 39,
DOWN: 40,
LEFT: 37,
POS1: 36,
END: 35,
DELETE: 46,
BACKSPACE: 8,
TAB: 9,
A: 65
}
function KeyBinding(element, host)
{
addListener(element, "keydown", function(e)
{
var key = e.keyCode;
switch (key)
{
case keys.A:
if (e.metaKey)
{
host.selectAll();
return stopEvent(e);
}
break;
case keys.UP:
if (e.shiftKey) {
host.selectUp();
} else {
host.clearSelection();
host.moveUp();
}
return stopEvent(e);
case keys.DOWN:
if (e.shiftKey) {
host.selectDown();
} else {
host.clearSelection();
host.moveDown();
}
return stopEvent(e);
case keys.LEFT:
if (e.metaKey && e.shiftKey) {
host.selectLineStart();
} else if (e.metaKey) {
host.clearSelection();
host.moveLineStart();
} else if (e.shiftKey) {
host.selectLeft();
} else {
host.clearSelection();
host.moveLeft();
}
return stopEvent(e);
case keys.RIGHT:
if (e.metaKey && e.shiftKey) {
host.selectLineEnd();
} else if (e.metaKey) {
host.clearSelection();
host.moveLineEnd();
} else if (e.shiftKey) {
host.selectRight();
} else {
host.clearSelection();
host.moveRight();
}
return stopEvent(e);
case keys.POS1:
if (e.shiftKey) {
host.selectLineStart();
} else {
host.clearSelection();
host.moveLineStart();
}
return stopEvent(e);
case keys.END:
if (e.shiftKey) {
host.selectLineEnd();
} else {
host.clearSelection();
host.moveLineEnd();
}
return stopEvent(e);
case keys.DELETE:
host.clearSelection();
host.removeRight();
return stopEvent(e);
case keys.BACKSPACE:
host.clearSelection();
host.removeLeft();
return stopEvent(e);
case keys.TAB:
host.onTextInput(" ");
return stopEvent(e);
}
});
};
function Editor(doc, renderer)
{
var container = renderer.getContainerElement();
this.renderer = renderer;
var textInput = new TextInput(container, this);
new KeyBinding(container, this);
addListener(container, "mousedown", bind(this.onMouseDown, this));
addListener(container, "mousewheel", bind(this.onMouseWheel, this));
this.doc = doc;
renderer.setDocument(doc);
this.cursor = {
row: 0,
column: 0
};
this.selectionAnchor = null;
this.selectionLead = null;
this.selection = null;
this.draw();
}
Editor.prototype =
{
draw : function()
{
this.renderer.draw();
this.renderer.updateCursor(this.cursor);
},
resize : function() {
this.renderer.draw();
},
updateCursor : function() {
this.renderer.updateCursor(this.cursor);
},
onFocus : function() {
this.renderer.showCursor();
this.renderer.visualizeFocus();
},
onBlur : function() {
this.renderer.hideCursor();
this.renderer.visualizeBlur();
},
onMouseDown : function(e)
{
this.textInput.focus();
var pos = this.renderer.screenToTextCoordinates(pageX, pageY);
this.moveTo(pos.row, pos.column);
this.setSelectionAnchor(pos.row, pos.column);
this.renderer.scrollCursorIntoView();
return preventDefault(e);
},
onMouseWheel : function(e)
{
var delta = e.wheelDeltaY;
this.renderer.scrollToY(this.renderer.getScrollTop() - (delta/10));
return preventDefault(e);
},
getCopyText : function()
{
if (this.hasSelection()) {
return this.doc.getTextRange(this.getSelectionRange());
} else {
return "";
}
},
onCut : function()
{
if (this.hasSelection())
{
this.cursor = this.doc.remove(this.getSelectionRange());
this.clearSelection();
this.draw();
}
},
onTextInput: function(text)
{
this.cursor = this.doc.insert(this.cursor, text);
this.clearSelection();
this.draw();
this.renderer.scrollCursorIntoView();
},
removeRight : function()
{
var rangeEnd = {
row: this.cursor.row,
column: this.cursor.column + 1
}
if (rangeEnd.column > this.doc.getLine(this.cursor.row).length) {
rangeEnd.row += 1;
rangeEnd.column = 0;
}
this.doc.remove({start: this.cursor, end: renageEnd});
this.draw();
this.renderer.scrollCursorIntoView();
},
removeLeft : function()
{
if (this.cursor.row == 0 && this.cursor.column == 0) {
return;
}
var rangeStart = {
row: this.cursor.row,
column: this.cursor.column + -1
}
if (rangeStart.column < 0)
{
rangeStart.row -= 1;
rangeStart.column = this.doc.getLine(this.cursor.row-1).length;
}
this.cursor = this.doc.remove({start: rangeStart, end: this.cursor});
this.draw();
this.renderer.scrollCursorIntoView();
},
onCompositionStart : function()
{
this.renderer.showComposition(this.cursor);
this.onTextInput(" ");
},
onCompositionUpdate : function(text) {
this.renderer.setCompositionText(text);
},
onCompositionEnd : function() {
this.renderer.hideComposition();
this.removeLeft();
},
moveUp : function() {
this.moveBy(-1, 0);
this.renderer.scrollCursorIntoView();
},
moveDown : function() {
this.moveBy(1, 0);
this.renderer.scrollCursorIntoView();
},
moveLeft : function()
{
if (this.cursor.column == 0) {
if (this.cursor.row > 0) {
this.moveTo(this.cursor.row-1, this.doc.getLine(this.cursor.row-1).length);
}
} else {
this.moveBy(0, -1);
}
this.renderer.scrollCursorIntoView();
},
moveRight : function()
{
if (this.cursor.column == this.doc.getLine(this.cursor.row).length) {
if (this.cursor.row < this.doc.getLength()-1) {
this.moveTo(this.cursor.row+1, 0);
}
} else {
this.moveBy(0, 1);
}
this.renderer.scrollCursorIntoView();
},
moveLineStart : function()
{
this.moveTo(this.cursor.row, 0);
this.renderer.scrollCursorIntoView();
},
moveLineEnd : function() {
this.moveTo(this.cursor.row, this.doc.getLine(this.cursor.row).length);
this.renderer.scrollCursorIntoView();
},
hasSelection : function() {
return !!this.selectionLead;
},
setSelectionAnchor : function(row, column)
{
this.selectionAnchor = {
row: row,
column: column
};
this.selectionLead = null;
},
getSelectionRange : function()
{
var anchor = this.selectionAnchor;
var lead = this.selectionLead;
if (!anchor) {
return null;
} else {
if (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column)) {
return {
start: lead,
end: anchor
}
} else {
return {
start: anchor,
end: lead
}
}
}
},
clearSelection : function()
{
this.selectionLead = null;
this.selectionAnchor = null;
if (this.selection) {
this.renderer.removeMarker(this.selection);
this.selection = null;
}
},
selectAll : function()
{
var lastRow = this.doc.getLength()-1;
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
this._moveSelection(function() {
this.moveTo(0, 0);
});
},
_moveSelection : function(mover)
{
if (!this.selectionAnchor) {
this.selectionAnchor = {
row: this.cursor.row,
column: this.cursor.column
}
}
mover.call(this);
this.selectionLead = {
row: this.cursor.row,
column: this.cursor.column
}
if (this.selection) {
this.renderer.updateMarker(this.selection, this.getSelectionRange());
} else {
this.selection = this.renderer.addMarker(this.getSelectionRange(), "selection");
}
},
selectUp : function() {
this._moveSelection(this.moveUp);
},
selectDown : function() {
this._moveSelection(this.moveDown);
},
selectRight : function() {
this._moveSelection(this.moveRight);
},
selectLeft : function() {
this._moveSelection(this.moveLeft);
},
selectLineStart : function() {
this._moveSelection(this.moveLineStart);
},
selectLineEnd : function() {
this._moveSelection(this.moveLineEnd);
},
moveBy : function(rows, chars) {
this.moveTo(this.cursor.row+rows, this.cursor.column+chars);
},
moveTo : function(row, column)
{
this.cursor.row = Math.min(this.doc.getLength()-1, Math.max(0, row));
this.cursor.column = Math.min(this.doc.getLine(this.cursor.row).length, Math.max(0, column));
this.updateCursor();
}
}