-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode-editor.js
More file actions
129 lines (119 loc) · 4.22 KB
/
code-editor.js
File metadata and controls
129 lines (119 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
var KEY_TAB = 9;
var KEY_BACK = 8;
var KEY_ENTER = 13;
var TAB_REPLACE = " ";
// TODO A good method for detecting attempts to set beyond the selection end or before the beginning of the text
var moveSelectionStart = function(elem, start) {
var moved; // how many chars actually moved
if (elem.selectionStart !== undefined) { // Firefox
if (elem.selectionStart + start < 0) { // if attempts to set before beginning of text
moved = -elem.selectionStart;
elem.selectionStart = 0;
} else {
moved = start;
elem.selectionStart = elem.selectionStart + start;
}
//alert(elem.selectionStart);
} else {
var range = document.selection.createRange();
var beginRange = range.duplicate();
beginRange.moveToElementText(elem);
beginRange.setEndPoint("EndToStart", range);
if (beginRange.text.length < -start) { // if attempts to set befire beginning of text
moved = -beginRange.text.length;
} else {
moved = start;
}
range.moveStart("character", moved);
range.select();
}
return moved;
};
var getSelection = function(elem) {
if (elem.selectionStart !== undefined && elem.selectionEnd !== undefined) { // stupid implicit type-casting
return elem.value.substring(elem.selectionStart,
elem.selectionEnd);
} else {
return document.selection.createRange().text;
}
};
var replaceSelection = function(elem, text, cursorAtStart) {
if (elem.selectionStart !== undefined && elem.selectionEnd !== undefined) { // Firefox
var start = elem.selectionStart;
var end = elem.selectionEnd;
var len = elem.value.length;
elem.value = elem.value.substring(0, start) +
text +
elem.value.substring(end, len);
elem.selectionStart = start + text.length;
elem.selectionEnd = start + text.length;
} else { // everything else
var range = document.selection.createRange();
range.text = text;
range.collapse();
range.select();
}
};
var stopDefault = function(e) {
if (e.preventDefault) { // W3C method
e.preventDefault();
} else { // internet exploder
e.returnValue = false;
}
};
// move selection start to the beginning of the line
var selectLine = function(elem) {
var c = "";
var moved = 0;
// Internet Exploder uses vertical tab for some reason
while ((c !== "\n" && c !== "\x0D") && moveSelectionStart(elem, -1) === -1) {
c = getSelection(elem).charAt(0);
moved -= 1;
}
if (c === "\n" || c === "\x0D") {
moveSelectionStart(elem, 1);
moved += 1;
}
return moved;
};
var onKeyDownCallback = function(editor, e) {
var moved;
if (e.keyCode === KEY_TAB) { // insert soft-tab
stopDefault(e);
replaceSelection(editor, TAB_REPLACE, false);
} else if (e.keyCode === KEY_BACK &&
getSelection(editor) === "") {
// proceed if only nothing is selected
moved = moveSelectionStart(editor, -TAB_REPLACE.length);
var sel = getSelection(editor);
if (sel === TAB_REPLACE) {
// if there is a soft-tab, then erase it with one keystroke
stopDefault(e);
replaceSelection(editor, "");
} else {
moveSelectionStart(editor, -moved);
}
} else if (e.keyCode === KEY_ENTER) { // autoindent
moved = selectLine(editor);
var spaces = getSelection(editor).match(/(\s*)/)[0];
moveSelectionStart(editor, -moved);
setTimeout(function() {
replaceSelection(editor, spaces);
}, 0);
}
};
var addEventCallback = (window.addEventListener) ?
function(elem, name, callback) { // W3C Events
elem.addEventListener(name, callback, false);
} :
function(elem, name, callback) { // Internet Exploder
elem.attachEvent("on" + name, function() {
callback(window.event);
});
};
addEventCallback(window, "load", function(e) {
var editor = document.getElementById("editor");
addEventCallback(editor, "keydown", function(e) {
onKeyDownCallback(editor, e);
});
});