I have HTML textarea. I want to modify it, so that it implements auto-indentation, i.e. after NEWLINE is inserted, I want to automatically insert spaces at the beginning of the new line (the number of spaces depending on the indentation of the previous line). I figured out, that I can do it by registering a handler listening to 'keypress' event. Now I have a choice: (a) leave the default handler and insert the spaces AFTER the browser adds newline to the textarea.value, or (b) use preventDefault() and insert the whole thing (i.e. newline and spaces) by myself.
In case (a), illustrated by the code below, my handler is executed BEFORE the browser adds a newline, so the spaces (or '--' for illustration) end up at the end of the line, not at the beginning of the new one.
In case (b), shown in comments in the code below, the text is modified correctly, but if it results in cursor going out of the textarea view, the content is not scrolled (most likely because content scrolling is a part of default handling), so the cursor disappears behind the textarea boundary, and reappears only if I send another keystroke (i.e. not a newline).
How to achieve the auto-indentation effect without losing the default scrolling?
I know that this effect can possibly be approximated by delaying the insertion of spaces (e.g. with setTimeout()), so that the runtime has enough time to complete the default handling (i.e. insertion of the newline and vertical scrolling), but it seems like a huge kludge to me and introduction of a race condition that I am afraid is going to hit me under least expected circumstances (massive copy-paste, runtime slow due to other actions, high keyboard repetition rate etc.). Ideally I would like either (i) to have my code called after the default handling or (ii) to be able to prevent default handling, run my code, and explicitly call default handling. How to achieve it?
Thanks!
Greg
PS: I am not interested in integrating sophisticated textarea replacements, e.g. Editarea (I use one and it is very fragile across browsers).
Tested on FF3.
<html>
<head>
<script type="text/javascript">
function onKeyPressHandler(e) {
if (e.which == 13) // ASCII newline
{
var start = this.selectionStart;
var end = this.selectionEnd;
var v = this.value;
this.value = v.slice(0, start) + '--' + v.slice(end); // (a)
// (b): this.value = v.slice(0, start) + '\n--' + v.slice(end);
// (b): e.preventDefault();
}
}
onload = function() {
var editor = document.getElementById("editor");
editor.addEventListener('keypress', onKeyPressHandler, false);
}
</script>
</head>
<body>
<textarea rows="20" cols="80" id="editor"></textarea>
</body>
</html>