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

标签 javascript textarea indentation

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

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

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

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

我知道可以通过延迟插入空格(例如使用 setTimeout())来近似这种效果,以便运行时有足够的时间来完成默认处理(即插入换行符和垂直滚动),但是对我来说,这似乎是一个巨大的困惑,而且我担心引入竞争条件会在最意想不到的情况下打击我(大量复制粘贴、由于其他操作导致运行时间变慢、键盘重复率高等)。理想情况下,我希望 (i) 在默认处理之后调用我的代码,或者 (ii) 能够阻止默认处理、运行我的代码并显式调用默认处理。如何实现?

谢谢!

格雷格

PS:我对集成复杂的文本区域替换不感兴趣,例如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>

最佳答案

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

$("textarea").keydown(function(e)
{
    if (e.which == 9) //ASCII tab
    {
        e.preventDefault();
        var start = this.selectionStart;
        var end = this.selectionEnd;
        var v = $(this).val();
        if (start == end)
        {
            $(this).val(v.slice(0, start) + "    " + v.slice(start));
            this.selectionStart = start+4;
            this.selectionEnd = start+4;
            return;
        }

        var selectedLines = [];
        var inSelection = false;
        var lineNumber = 0;
        for (var i = 0; i < v.length; i++)
        {
            if (i == start)
            {
                inSelection = true;
                selectedLines.push(lineNumber);
            }
            if (i >= end)
                inSelection = false;

            if (v[i] == "\n")
            {
                lineNumber++;
                if (inSelection)
                    selectedLines.push(lineNumber);
            }
        }
        var lines = v.split("\n");
        for (var i = 0; i < selectedLines.length; i++)
        {
            lines[selectedLines[i]] = "    " + lines[selectedLines[i]];
        }

        $(this).val(lines.join("\n"));
    }
});
$("textarea").keypress(function(e)
{
    if (e.which == 13) // ASCII newline
    {
        setTimeout(function(that)
        {
            var start = that.selectionStart;
            var v = $(that).val();
            var thisLine = "";
            var indentation = 0;
            for (var i = start-2; i >= 0 && v[i] != "\n"; i--)
            {
                thisLine = v[i] + thisLine;
            }
            for (var i = 0; i < thisLine.length && thisLine[i] == " "; i++)
            {

                indentation++;
             }
             $(that).val(v.slice(0, start) + " ".repeat(indentation) + v.slice(start));
             that.selectionStart = start+indentation;
             that.selectionEnd = start+indentation;  
}, 0.01, this);
     }
});
<textarea rows="20" cols="40"></textarea>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

关于javascript - 如何将自动缩进添加到 HTML 文本区域?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5743916/

相关文章:

javascript - Rails : Tawk. 到聊天插件和 Turbolinks 问题

javascript - 我怎样才能滚动到并可能突出显示 div 中的文本溢出 : true?

ipad - jQuery Mobile 响应式面板和 Textarea

Android - 在 TextView 上缩进文本

Vim 中的 Ruby 代码自动缩进

c# - 母版页链接的背景颜色在 Internet Explorer 中发生变化,但在 Mozilla Firefox 中不起作用

javascript - 哪些版本的移动 WebKit 支持 JavaScript Workers?

c# - 描述 bool 值的 json

php 从文本区域获取值时出错

vim - 如何避免使用 vim cindent 缩进注释 block ?