Skip to content

Instantly share code, notes, and snippets.

@JosePedroDias
Created April 14, 2015 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JosePedroDias/87c75a647b338ef69ab3 to your computer and use it in GitHub Desktop.
Save JosePedroDias/87c75a647b338ef69ab3 to your computer and use it in GitHub Desktop.
textarea on steroids // source http://jsbin.com/babubo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>textarea on steroids</title>
<style id="jsbin-css">
html, body { height: 100%; }
body {
padding: 0;
margin: 0;
overflow: hidden;
}
textarea {
width: 100%;
height: 100%;
overflow: auto;
border-width: 0;
}
pre {
position: absolute;
right: 0;
bottom: 0;
background-color: #DDD;
padding: 8px;
opacity: 0.5;
}
</style>
</head>
<body>
<textarea autofocus spellcheck="false">
1 um
1.1 um ponto um
2 dois
2.1 dois ponto um
2.2 dois ponto dois
2.2.1 dois ponto dois ponto um
2.2.2 dois ponto dois ponto dois
3 três
3.1 três ponto um
</textarea>
<pre>
ctrl + up - <b>move line up</b>
ctrl + down - <b>move line down</b>
ctrl + right | tab - <b>indent</b>
ctrl + left | shift + tab - <b>dedent</b></pre>
<script id="jsbin-javascript">
var TAB = 9;
var LEFT = 37;
var UP = 38;
var RIGHT = 39;
var DOWN = 40;
var chars = function(n, c) {
return new Array(n+1).join(c);
};
var findPos = function(el) {
var cur = el.selectionStart;
var line, lines = el.value.split('\n');
var i = 0, y = 0, x = 0;
var X, Y = lines.length;
var o = {x:0, y:0, i:0, lines:lines, Y:Y};
for (y = 0; y < Y; ++y) {
line = lines[y];
X = line.length;
for (x = 0; x < X; ++x, ++i) {
if (i === cur) { o.x=x; o.y=y; o.i=i; return o; }
}
if (i === cur) { o.x=x; o.y=y; o.i=i; return o; }
++i;
}
};
var ta = function(el, tabLen) {
var oneTab = chars(tabLen, ' ');
//test this
el.value = el.value.replace( new RegExp('\\t', 'g'), oneTab);
el.addEventListener('keydown', function(ev) {
var ctrl = ev.ctrlKey;
var kc = ev.keyCode;
// cast tab keys to ctrl + dir keys
if (kc===TAB && !ctrl && !ev.altKey && !ev.metaKey) {
ctrl = true;
kc = ev.shiftKey ? LEFT : RIGHT;
}
// ctrl + dir handling
if (ctrl && (kc===LEFT || kc===RIGHT || kc===UP || kc===DOWN)) {
ev.preventDefault();
ev.stopPropagation();
var p = findPos(el);
var i = p.i;
var y = p.y;
var lines = p.lines;
var tmp;
if (kc === RIGHT) {
lines[y] = oneTab + lines[y];
i += tabLen;
}
else if (kc === LEFT) {
lines[y] = lines[y].replace( new RegExp('^ {'+tabLen+'}') , '');
i -= tabLen;
}
else if (kc === UP && y > 0) {
i -= lines[y-1].length + 1;
tmp = lines[y];
lines[y] = lines[y-1];
lines[y-1] = tmp;
}
else if (kc === DOWN && y < p.Y-1) {
i += lines[y+1].length + 1;
tmp = lines[y];
lines[y] = lines[y+1];
lines[y+1] = tmp;
}
el.value = lines.join('\n');
el.selectionStart = i;
el.selectionEnd = i;
}
});
};
ta( document.querySelector('textarea'), 4);
</script>
<script id="jsbin-source-html" type="text/html"><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>textarea on steroids</title>
</head>
<body>
<textarea autofocus spellcheck="false">
1 um
1.1 um ponto um
2 dois
2.1 dois ponto um
2.2 dois ponto dois
2.2.1 dois ponto dois ponto um
2.2.2 dois ponto dois ponto dois
3 três
3.1 três ponto um
</textarea>
<pre>
ctrl + up - <b>move line up</b>
ctrl + down - <b>move line down</b>
ctrl + right | tab - <b>indent</b>
ctrl + left | shift + tab - <b>dedent</b></pre>
</body>
</html>
</script>
<script id="jsbin-source-css" type="text/css">html, body { height: 100%; }
body {
padding: 0;
margin: 0;
overflow: hidden;
}
textarea {
width: 100%;
height: 100%;
overflow: auto;
border-width: 0;
}
pre {
position: absolute;
right: 0;
bottom: 0;
background-color: #DDD;
padding: 8px;
opacity: 0.5;
}</script>
<script id="jsbin-source-javascript" type="text/javascript">var TAB = 9;
var LEFT = 37;
var UP = 38;
var RIGHT = 39;
var DOWN = 40;
var chars = function(n, c) {
return new Array(n+1).join(c);
};
var findPos = function(el) {
var cur = el.selectionStart;
var line, lines = el.value.split('\n');
var i = 0, y = 0, x = 0;
var X, Y = lines.length;
var o = {x:0, y:0, i:0, lines:lines, Y:Y};
for (y = 0; y < Y; ++y) {
line = lines[y];
X = line.length;
for (x = 0; x < X; ++x, ++i) {
if (i === cur) { o.x=x; o.y=y; o.i=i; return o; }
}
if (i === cur) { o.x=x; o.y=y; o.i=i; return o; }
++i;
}
};
var ta = function(el, tabLen) {
var oneTab = chars(tabLen, ' ');
//test this
el.value = el.value.replace( new RegExp('\\t', 'g'), oneTab);
el.addEventListener('keydown', function(ev) {
var ctrl = ev.ctrlKey;
var kc = ev.keyCode;
// cast tab keys to ctrl + dir keys
if (kc===TAB && !ctrl && !ev.altKey && !ev.metaKey) {
ctrl = true;
kc = ev.shiftKey ? LEFT : RIGHT;
}
// ctrl + dir handling
if (ctrl && (kc===LEFT || kc===RIGHT || kc===UP || kc===DOWN)) {
ev.preventDefault();
ev.stopPropagation();
var p = findPos(el);
var i = p.i;
var y = p.y;
var lines = p.lines;
var tmp;
if (kc === RIGHT) {
lines[y] = oneTab + lines[y];
i += tabLen;
}
else if (kc === LEFT) {
lines[y] = lines[y].replace( new RegExp('^ {'+tabLen+'}') , '');
i -= tabLen;
}
else if (kc === UP && y > 0) {
i -= lines[y-1].length + 1;
tmp = lines[y];
lines[y] = lines[y-1];
lines[y-1] = tmp;
}
else if (kc === DOWN && y < p.Y-1) {
i += lines[y+1].length + 1;
tmp = lines[y];
lines[y] = lines[y+1];
lines[y+1] = tmp;
}
el.value = lines.join('\n');
el.selectionStart = i;
el.selectionEnd = i;
}
});
};
ta( document.querySelector('textarea'), 4);
</script></body>
</html>
html, body { height: 100%; }
body {
padding: 0;
margin: 0;
overflow: hidden;
}
textarea {
width: 100%;
height: 100%;
overflow: auto;
border-width: 0;
}
pre {
position: absolute;
right: 0;
bottom: 0;
background-color: #DDD;
padding: 8px;
opacity: 0.5;
}
var TAB = 9;
var LEFT = 37;
var UP = 38;
var RIGHT = 39;
var DOWN = 40;
var chars = function(n, c) {
return new Array(n+1).join(c);
};
var findPos = function(el) {
var cur = el.selectionStart;
var line, lines = el.value.split('\n');
var i = 0, y = 0, x = 0;
var X, Y = lines.length;
var o = {x:0, y:0, i:0, lines:lines, Y:Y};
for (y = 0; y < Y; ++y) {
line = lines[y];
X = line.length;
for (x = 0; x < X; ++x, ++i) {
if (i === cur) { o.x=x; o.y=y; o.i=i; return o; }
}
if (i === cur) { o.x=x; o.y=y; o.i=i; return o; }
++i;
}
};
var ta = function(el, tabLen) {
var oneTab = chars(tabLen, ' ');
//test this
el.value = el.value.replace( new RegExp('\\t', 'g'), oneTab);
el.addEventListener('keydown', function(ev) {
var ctrl = ev.ctrlKey;
var kc = ev.keyCode;
// cast tab keys to ctrl + dir keys
if (kc===TAB && !ctrl && !ev.altKey && !ev.metaKey) {
ctrl = true;
kc = ev.shiftKey ? LEFT : RIGHT;
}
// ctrl + dir handling
if (ctrl && (kc===LEFT || kc===RIGHT || kc===UP || kc===DOWN)) {
ev.preventDefault();
ev.stopPropagation();
var p = findPos(el);
var i = p.i;
var y = p.y;
var lines = p.lines;
var tmp;
if (kc === RIGHT) {
lines[y] = oneTab + lines[y];
i += tabLen;
}
else if (kc === LEFT) {
lines[y] = lines[y].replace( new RegExp('^ {'+tabLen+'}') , '');
i -= tabLen;
}
else if (kc === UP && y > 0) {
i -= lines[y-1].length + 1;
tmp = lines[y];
lines[y] = lines[y-1];
lines[y-1] = tmp;
}
else if (kc === DOWN && y < p.Y-1) {
i += lines[y+1].length + 1;
tmp = lines[y];
lines[y] = lines[y+1];
lines[y+1] = tmp;
}
el.value = lines.join('\n');
el.selectionStart = i;
el.selectionEnd = i;
}
});
};
ta( document.querySelector('textarea'), 4);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment