Оказывается, для W3C-совместимых даже не нужен объект Range, все еще проще:
<textarea id="memo1" cols="25" rows="5">aaaa bbbb cccc</textarea>
<input type="button" onmousedown="add_tags('[b]', '[/b]')" onclick="restore_selection()" value="Bold" />
<script type="text/javascript">
var ie //@cc_on = true;
var range;
var textarea = document.getElementById("memo1");
function add_tags(str1, str2) {
var text, offset;
var selection = document.selection || getSelection();
if(ie) {
range = selection.createRange();
text = range.text;
range.text = str1 + text + str2;
offset = str2.length;
range.moveStart("character", -text.length - offset);
if(text.length) {
range.moveEnd("character", -offset);
} else {
range.collapse();
}
} else {
var selStart = textarea.selectionStart;
var selEnd = textarea.selectionEnd;
text = textarea.value;
textarea.value = text.substring(0, selStart) + str1 + text.substring(selStart, selEnd) + str2 + text.substring(selEnd, text.length);
offset = str1.length;
textarea.selectionStart = selStart + offset;
textarea.selectionEnd = selEnd + offset;
}
}
function restore_selection() {
textarea.focus();
if(ie) {
range.select();
}
}
</script>