summaryrefslogtreecommitdiff
path: root/editor/editor.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor.ts')
-rw-r--r--editor/editor.ts93
1 files changed, 75 insertions, 18 deletions
diff --git a/editor/editor.ts b/editor/editor.ts
index e95b858..962ebb5 100644
--- a/editor/editor.ts
+++ b/editor/editor.ts
@@ -23,8 +23,9 @@ export class WuiEditor {
id: string;
is_editable: boolean;
lines: WuiEditorLine[] = [];
+ sel!: Selection;
+ selLineStart: number = 0;
private el!: HTMLElement;
- private sel!: Selection;
private range_begin: number = -1;
private range_end: number = -1;
private raw_lines: string[] = [];
@@ -61,6 +62,28 @@ export class WuiEditor {
document.onkeyup = (ev: KeyboardEvent) => {
this.onKeyupDocument(this, ev);
};
+
+ // Handle system COPY event.
+ // For each selection range, add line-feed to the end of it, unless the
+ // line is empty, so when we paste it back we can iterate the lines and
+ // insert it as new line.
+ this.el.addEventListener("copy", (ev: ClipboardEvent) => {
+ ev.preventDefault();
+ let text = "";
+ let line = "";
+ for (let i = 0; i < this.sel.rangeCount; i++) {
+ line = this.sel.getRangeAt(i)?.toString();
+ if (!line) {
+ continue;
+ }
+ text += line;
+
+ if (line != "\n") {
+ text += "\n";
+ }
+ }
+ ev.clipboardData?.setData("text/plain", text);
+ });
}
// getContent return content of file.
@@ -82,13 +105,6 @@ export class WuiEditor {
} as RangeInterface;
}
- onClickText() {
- const sel = window.getSelection();
- if (sel) {
- this.sel = sel;
- }
- }
-
// onKeyDelete handle key "DELETE" event on line.
//
// Case 1: DELETE on selection.
@@ -101,10 +117,10 @@ export class WuiEditor {
onKeyDelete(x: number, ev: KeyboardEvent) {
ev.preventDefault();
- let elTextCurrent = this.lines[x]!.elText;
- let textCurr = elTextCurrent.innerText;
+ const elTextCurrent = this.lines[x]!.elText;
+ const textCurr = elTextCurrent.innerText;
- let selString = this.sel.toString();
+ const selString = this.sel.toString();
if (selString.length > 0) {
// Case 1: DELETE on selection.
let textAfter = textCurr.slice(0, this.sel.anchorOffset);
@@ -115,7 +131,7 @@ export class WuiEditor {
}
let textAfter = "";
- let off = this.sel.focusOffset;
+ const off = this.sel.focusOffset;
if (off === textCurr.length) {
// Case 2: DELETE on the end of line.
@@ -505,7 +521,7 @@ export class WuiEditor {
this.render();
}
- private insertNewline(x: number, text: string) {
+ insertNewline(x: number, text: string) {
const newline = new WuiEditorLine(x, text, this);
for (let y = x; y < this.lines.length; y++) {
this.lines[y]?.setNumber(y + 1);
@@ -594,6 +610,10 @@ class WuiEditorLine {
ed: WuiEditor,
) {
this.lineNum = x;
+ if (text == "") {
+ // Add line feed to make all lines layout consistent.
+ text = "\n";
+ }
this.el = document.createElement("div");
this.el.classList.add(WUI_EDITOR_CLASS_LINE);
@@ -613,10 +633,6 @@ class WuiEditorLine {
this.elText.innerText = text;
this.elText.contentEditable = "true";
- this.elText.onclick = () => {
- ed.onClickText();
- };
-
this.elText.onkeydown = (ev: KeyboardEvent) => {
return ed.onKeydownOnLine(this.lineNum, ev);
};
@@ -624,13 +640,54 @@ class WuiEditorLine {
return ed.onKeyupOnLine(this.lineNum, ev);
};
+ // onmousedown get and store the current selection and current line
+ // number so we can do multiple selection later when mouse move up or
+ // down.
+ this.elText.onmousedown = () => {
+ ed.sel.removeAllRanges();
+
+ const sel = window.getSelection();
+ if (!sel) {
+ return;
+ }
+
+ ed.sel = sel;
+ ed.selLineStart = this.x;
+ };
+
+ this.elText.onmouseup = () => {
+ ed.selLineStart = 0;
+ };
+
+ // onmousemove if the current line not same when the mousedown started,
+ // add it to selection range.
+ this.elText.onmousemove = () => {
+ if (!ed.selLineStart) {
+ return;
+ }
+ if (ed.selLineStart == this.x) {
+ return;
+ }
+
+ const range = document.createRange();
+ range.selectNode(this.elText);
+ ed.sel.addRange(range);
+ };
+
+ // paste event we split the clipboard text into lines and it to editor
+ // line by line.
this.elText.addEventListener("paste", (ev: ClipboardEvent) => {
if (!ev.clipboardData) {
return;
}
+
ev.preventDefault();
+
const text = ev.clipboardData.getData("text/plain");
- document.execCommand("insertHTML", false, text);
+ const lines = text.split("\n");
+ lines.forEach((l: string, x: number) => {
+ ed.insertNewline(this.x + x, l);
+ });
});
this.el.appendChild(this.el_number);