make selections work
This commit is contained in:
parent
08f14e321f
commit
7c845509d7
3 changed files with 169 additions and 54 deletions
215
Editor.js
215
Editor.js
|
|
@ -90,7 +90,8 @@ var keys = {
|
||||||
END: 35,
|
END: 35,
|
||||||
DELETE: 46,
|
DELETE: 46,
|
||||||
BACKSPACE: 8,
|
BACKSPACE: 8,
|
||||||
TAB: 9
|
TAB: 9,
|
||||||
|
A: 65
|
||||||
}
|
}
|
||||||
|
|
||||||
function KeyBinding(element, host)
|
function KeyBinding(element, host)
|
||||||
|
|
@ -98,54 +99,88 @@ function KeyBinding(element, host)
|
||||||
addListener(element, "keydown", function(e)
|
addListener(element, "keydown", function(e)
|
||||||
{
|
{
|
||||||
var key = e.keyCode;
|
var key = e.keyCode;
|
||||||
|
|
||||||
// TODO
|
|
||||||
/*
|
|
||||||
if (!e.shiftKey) {
|
|
||||||
host.clearSelection();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
case keys.A:
|
||||||
|
if (e.metaKey)
|
||||||
|
{
|
||||||
|
host.selectAll();
|
||||||
|
return stopEvent(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case keys.UP:
|
case keys.UP:
|
||||||
host.moveUp();
|
if (e.shiftKey) {
|
||||||
|
host.selectUp();
|
||||||
|
} else {
|
||||||
|
host.clearSelection();
|
||||||
|
host.moveUp();
|
||||||
|
}
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
case keys.DOWN:
|
case keys.DOWN:
|
||||||
host.moveDown();
|
if (e.shiftKey) {
|
||||||
|
host.selectDown();
|
||||||
|
} else {
|
||||||
|
host.clearSelection();
|
||||||
|
host.moveDown();
|
||||||
|
}
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
case keys.LEFT:
|
case keys.LEFT:
|
||||||
if (e.metaKey) {
|
if (e.metaKey && e.shiftKey) {
|
||||||
|
host.selectLineStart();
|
||||||
|
} else if (e.metaKey) {
|
||||||
|
host.clearSelection();
|
||||||
host.moveLineStart();
|
host.moveLineStart();
|
||||||
|
} else if (e.shiftKey) {
|
||||||
|
host.selectLeft();
|
||||||
} else {
|
} else {
|
||||||
|
host.clearSelection();
|
||||||
host.moveLeft();
|
host.moveLeft();
|
||||||
}
|
}
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
case keys.RIGHT:
|
case keys.RIGHT:
|
||||||
if (e.metaKey) {
|
if (e.metaKey && e.shiftKey) {
|
||||||
|
host.selectLineEnd();
|
||||||
|
} else if (e.metaKey) {
|
||||||
|
host.clearSelection();
|
||||||
host.moveLineEnd();
|
host.moveLineEnd();
|
||||||
} else if (e.shiftKey) {
|
} else if (e.shiftKey) {
|
||||||
host.selectRight();
|
host.selectRight();
|
||||||
} else {
|
} else {
|
||||||
|
host.clearSelection();
|
||||||
host.moveRight();
|
host.moveRight();
|
||||||
}
|
}
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
case keys.POS1:
|
case keys.POS1:
|
||||||
host.moveLineStart();
|
if (e.shiftKey) {
|
||||||
|
host.selectLineStart();
|
||||||
|
} else {
|
||||||
|
host.clearSelection();
|
||||||
|
host.moveLineStart();
|
||||||
|
}
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
case keys.END:
|
case keys.END:
|
||||||
host.moveLineEnd();
|
if (e.shiftKey) {
|
||||||
|
host.selectLineEnd();
|
||||||
|
} else {
|
||||||
|
host.clearSelection();
|
||||||
|
host.moveLineEnd();
|
||||||
|
}
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
case keys.DELETE:
|
case keys.DELETE:
|
||||||
|
host.clearSelection();
|
||||||
host.removeRight();
|
host.removeRight();
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
case keys.BACKSPACE:
|
case keys.BACKSPACE:
|
||||||
|
host.clearSelection();
|
||||||
host.removeLeft();
|
host.removeLeft();
|
||||||
return stopEvent(e);
|
return stopEvent(e);
|
||||||
|
|
||||||
|
|
@ -164,19 +199,8 @@ function Editor(doc, renderer)
|
||||||
var textInput = new TextInput(container, this);
|
var textInput = new TextInput(container, this);
|
||||||
new KeyBinding(container, this);
|
new KeyBinding(container, this);
|
||||||
|
|
||||||
var self = this;
|
addListener(container, "mousedown", bind(this.onMouseDown, this));
|
||||||
addListener(container, "mousedown", function(e) {
|
addListener(container, "mousewheel", bind(this.onMouseWheel, this));
|
||||||
textInput.focus();
|
|
||||||
self.placeCursorToMouse(e.pageX, e.pageY);
|
|
||||||
self.renderer.scrollCursorIntoView();
|
|
||||||
return preventDefault(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
addListener(container, "mousewheel", function(e) {
|
|
||||||
var delta = e.wheelDeltaY;
|
|
||||||
self.renderer.scrollToY(self.renderer.getScrollTop() - (delta/10));
|
|
||||||
return preventDefault(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.doc = doc;
|
this.doc = doc;
|
||||||
renderer.setDocument(doc);
|
renderer.setDocument(doc);
|
||||||
|
|
@ -186,7 +210,8 @@ function Editor(doc, renderer)
|
||||||
column: 0
|
column: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
this.selectionRange = null;
|
this.selectionAnchor = null;
|
||||||
|
this.selectionLead = null;
|
||||||
this.selection = null;
|
this.selection = null;
|
||||||
|
|
||||||
this.draw();
|
this.draw();
|
||||||
|
|
@ -218,10 +243,29 @@ Editor.prototype =
|
||||||
this.renderer.visualizeBlur();
|
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()
|
getCopyText : function()
|
||||||
{
|
{
|
||||||
if (this.selectionRange) {
|
if (this.hasSelection()) {
|
||||||
return this.doc.getTextRange(this.selectionRange);
|
return this.doc.getTextRange(this.getSelectionRange());
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
@ -229,29 +273,24 @@ Editor.prototype =
|
||||||
|
|
||||||
onCut : function()
|
onCut : function()
|
||||||
{
|
{
|
||||||
if (this.selectionRange)
|
if (this.hasSelection())
|
||||||
{
|
{
|
||||||
this.cursor = this.doc.remove(this.selectionRange);
|
this.cursor = this.doc.remove(this.getSelectionRange());
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.draw();
|
this.draw();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
placeCursorToMouse : function(pageX, pageY)
|
|
||||||
{
|
|
||||||
var pos = this.renderer.screenToTextCoordinates(pageX, pageY);
|
|
||||||
this.moveTo(pos.row, pos.column);
|
|
||||||
},
|
|
||||||
|
|
||||||
onTextInput: function(text)
|
onTextInput: function(text)
|
||||||
{
|
{
|
||||||
this.cursor = this.doc.insert(this.cursor, text);
|
this.cursor = this.doc.insert(this.cursor, text);
|
||||||
|
this.clearSelection();
|
||||||
this.draw();
|
this.draw();
|
||||||
this.renderer.scrollCursorIntoView();
|
this.renderer.scrollCursorIntoView();
|
||||||
},
|
},
|
||||||
|
|
||||||
removeRight : function()
|
removeRight : function()
|
||||||
{
|
{
|
||||||
var rangeEnd = {
|
var rangeEnd = {
|
||||||
row: this.cursor.row,
|
row: this.cursor.row,
|
||||||
column: this.cursor.column + 1
|
column: this.cursor.column + 1
|
||||||
|
|
@ -347,40 +386,110 @@ Editor.prototype =
|
||||||
this.renderer.scrollCursorIntoView();
|
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()
|
clearSelection : function()
|
||||||
{
|
{
|
||||||
this.selectionRange = null;
|
this.selectionLead = null;
|
||||||
|
this.selectionAnchor = null;
|
||||||
|
|
||||||
if (this.selection) {
|
if (this.selection) {
|
||||||
this.renderer.removeMarker(this.selection);
|
this.renderer.removeMarker(this.selection);
|
||||||
this.selection = null;
|
this.selection = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
selectRight : function()
|
selectAll : function()
|
||||||
{
|
{
|
||||||
if (!this.selectionRange) {
|
var lastRow = this.doc.getLength()-1;
|
||||||
this.selectionRange = {
|
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
|
||||||
start: {
|
|
||||||
row: this.cursor.row,
|
this._moveSelection(function() {
|
||||||
column: this.cursor.column
|
this.moveTo(0, 0);
|
||||||
}
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_moveSelection : function(mover)
|
||||||
|
{
|
||||||
|
if (!this.selectionAnchor) {
|
||||||
|
this.selectionAnchor = {
|
||||||
|
row: this.cursor.row,
|
||||||
|
column: this.cursor.column
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.moveRight();
|
mover.call(this);
|
||||||
|
|
||||||
this.selectionRange.end = {
|
this.selectionLead = {
|
||||||
row: this.cursor.row,
|
row: this.cursor.row,
|
||||||
column: this.cursor.column
|
column: this.cursor.column
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selection) {
|
if (this.selection) {
|
||||||
this.renderer.updateMarker(this.selection, this.selectionRange);
|
this.renderer.updateMarker(this.selection, this.getSelectionRange());
|
||||||
} else {
|
} else {
|
||||||
this.selection = this.renderer.addMarker(this.selectionRange, "selection");
|
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) {
|
moveBy : function(rows, chars) {
|
||||||
this.moveTo(this.cursor.row+rows, this.cursor.column+chars);
|
this.moveTo(this.cursor.row+rows, this.cursor.column+chars);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ function VirtualRenderer(containerId)
|
||||||
this.layers.push({
|
this.layers.push({
|
||||||
element: this.markerEl,
|
element: this.markerEl,
|
||||||
update: this.updateMarkers
|
update: this.updateMarkers
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualRenderer.prototype.setDocument = function(doc) {
|
VirtualRenderer.prototype.setDocument = function(doc) {
|
||||||
|
|
|
||||||
6
lib.js
6
lib.js
|
|
@ -72,4 +72,10 @@ computedStyle = function(element, style)
|
||||||
} else {
|
} else {
|
||||||
return element.currentStyle[style];
|
return element.currentStyle[style];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bind = function(fcn, context) {
|
||||||
|
return function() {
|
||||||
|
return fcn.apply(context, arguments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue