Javascript 如何将自动缩进添加到HTML文本区域?

Javascript 如何将自动缩进添加到HTML文本区域?,javascript,textarea,indentation,Javascript,Textarea,Indentation,我有HTML文本区。我想修改它,使其实现自动缩进,即插入换行后,我想在新行的开头自动插入空格(空格的数量取决于前一行的缩进)。我发现,我可以通过注册一个监听“keypress”事件的处理程序来实现这一点。现在我有一个选择:(a)在浏览器将换行符添加到textarea.value后保留默认处理程序并插入空格,或者(b)使用preventDefault()并自己插入整个内容(即换行符和空格) 在案例(a)中,如下面的代码所示,我的处理程序在浏览器添加换行符之前执行,因此空格(或用于说明的“--”)结

我有HTML文本区。我想修改它,使其实现自动缩进,即插入换行后,我想在新行的开头自动插入空格(空格的数量取决于前一行的缩进)。我发现,我可以通过注册一个监听“keypress”事件的处理程序来实现这一点。现在我有一个选择:(a)在浏览器将换行符添加到textarea.value后保留默认处理程序并插入空格,或者(b)使用preventDefault()并自己插入整个内容(即换行符和空格)

在案例(a)中,如下面的代码所示,我的处理程序在浏览器添加换行符之前执行,因此空格(或用于说明的“--”)结束于换行符的末尾,而不是新换行符的开头

在下面代码注释中显示的情况(b)中,文本被正确修改,但如果它导致光标离开textarea视图,则内容不会滚动(很可能是因为内容滚动是默认处理的一部分),因此光标会消失在textarea边界后,并且仅在我发送另一个按键时才会重新出现(即不是换行符)

如何在不丢失默认滚动的情况下实现自动缩进效果

我知道,可以通过延迟空格的插入(例如使用setTimeout())来近似这种效果,这样运行时就有足够的时间来完成默认处理(例如插入换行符和垂直滚动),但对我来说,这似乎是一个巨大的难题,引入了一个竞争条件,我担心在最不期望的情况下(大量复制粘贴、由于其他操作导致运行时缓慢、键盘重复率高等)会对我造成冲击。理想情况下,我希望(I)在默认处理后调用代码,或者(ii)要防止默认处理,请运行我的代码,并显式调用默认处理。如何实现它

谢谢

格雷格

PS:我对集成复杂的textarea替换不感兴趣,例如Editarea(我使用一个,它在浏览器中非常脆弱)

在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>

功能onKeyPressHandler(e){
if(e.which==13)//ASCII换行符
{
var start=this.selectionStart;
var end=this.selectionEnd;
var v=该值;
this.value=v.slice(0,开始)+'--'+v.slice(结束);//(a)
//(b):this.value=v.slice(0,开始)+'\n--'+v.slice(结束);
//(b):e.预防违约();
}
}
onload=函数(){
var editor=document.getElementById(“编辑器”);
addEventListener('keypress',onKeyPressHandler,false);
} 
查看以下内容:


另外,

这是大量借用的代码(谢谢,stackoverflow!),还有一些小的调整。第一部分只是创建一个mirrow,这样你就可以知道你在哪一行(与你的问题不太相关),但它包含一些设置当前缩进的内容,这一点很重要

$(document).keypress(function(e) {
  if (e.keyCode ==13){
    e.preventDefault();
    var start = $('textarea').get(0).selectionStart;
    var end = $('textarea').get(0).selectionEnd;
    // set textarea value to: text before caret + tab + text after caret
    var spaces = "\n" 
    for (i = 0; i < start; i++) { 
      spaces += " "
    }
   $('textarea').val($('textarea').val().substring(0, start)
      + spaces 
      + $('textarea').val().substring(end));

    // put caret at right position again
    console.log(spaces.length)
    $('textarea').get(0).selectionStart =
    $('textarea').get(0).selectionEnd = start + spaces.length;
  }
})
$(文档)。按键(功能(e){
如果(e.keyCode==13){
e、 预防默认值();
var start=$('textarea').get(0).selectionStart;
var end=$('textarea')。获取(0)。选择结束;
//将textarea值设置为:插入符号前的文本+制表符+插入符号后的文本
var spaces=“\n”
对于(i=0;i
虽然这篇文章已经有六年的历史了,但下面是如何自动缩进
textarea
s:

$(“textarea”).keydown(函数(e)
{
if(e.which==9)//ASCII制表符
{
e、 预防默认值();
var start=this.selectionStart;
var end=this.selectionEnd;
var v=$(this.val();
如果(开始==结束)
{
$(this.val(v.slice(0,start)+“”+v.slice(start));
返回;
}
var selectedLines=[];
var inSelection=false;
var lineNumber=0;
对于(变量i=0;i=结束)
插入选择=错误;
如果(v[i]=“\n”)
{
lineNumber++;
如果(插入选择)
选择行。按(行号);
}
}
变量行=v.split(“\n”);
对于(变量i=0;i=0&&v[i]!=“\n”i--)
{
这条线=v[i]+这条线;
}
对于(变量i=0;i

我修改了Leo的答案,以解决延迟问题(通过使用keypress而不是带有setTimeout的keyup),以及导致编辑文本中间部分不起作用的错误

$(“textarea”).keydown(函数(e)
{
if(e.which==9)//ASCII制表符
{
e、 预防默认值();
var start=this.selectionStart;
var end=this.selectionEnd;
var v=$(this.val();