代码之家  ›  专栏  ›  技术社区  ›  Robert

“智能”文本区域自动缩进

  •  5
  • Robert  · 技术社区  · 14 年前

        var start = this.selectionStart-1;
        var end = this.selectionEnd;
        var sT = this.scrollTop;
        var sH = this.scrollHeight;
        var vH = $(this).height();
    
        var x = (sH - sT) - vH;
    
        // Check if hitting enter on the first line as no newline will be found
        if (this.value.lastIndexOf('\n',start)==-1)
         var startSubstr = 0;
        else 
         var startSubstr = this.value.lastIndexOf('\n',start)+1;
    
        var endFirst = end - startSubstr;
    
        var valueToScan = this.value.substr(startSubstr,endFirst);
        var count = 0;
    
        // Count only \t at the beginning of the line, none in the code   
        while (valueToScan.indexOf('\t')!=-1) {
         if (valueToScan.indexOf('\t')!=0)
          break;
         count++;
         valueToScan = valueToScan.substr(valueToScan.indexOf('\t')+1);
        }
    
        // Command to isert the newline, and then add the \t's found in previously  
        $(this).insertAtCaret('\n');
        for (var i=0;i<count;count--) {
         $(this).insertAtCaret('\t');
        }  
    
        var sH = this.scrollHeight;
        this.scrollTop = (sH - x) - vH;
    

    编辑 作为更新,为了消除任何混淆,我尝试创建一个IDE样式的文本框,例如在大多数IDE中,如果您键入以下内容

    function example(whatever) {
         Example Stuff // And then hit enter here
    

    编辑2

    我一直在写这篇文章。我想当我有机会的时候,我将要探讨的另一个选择是不阻止enter,只允许按enter并从中读取字符串的默认操作 lastIndexOf('\n')-1 到最近的 \n 对于任何 \t

    编辑3 解决了,根据我以前的更新,我决定在按下键后扫描字符串,保留自然行为(下面为感兴趣的人添加了更改的部分),唯一真正剩下的问题是,如果您按住enter键,它将不计算从enter键的原点开始的缩进,这对我来说很好。我要把这个给你http://stackoverflow.com/users/15066/matyr'>玛蒂尔,虽然在他回答之前我就知道他还是最接近的。

    if (this.value.lastIndexOf('\n',start-2)==-1) {
     var startSubstr = 0;
    } else {
     var startSubstr = this.value.lastIndexOf('\n',start-1)+1;
    }    
    var valueToScan = this.value.substr(startSubstr,start);
    
    4 回复  |  直到 14 年前
        1
  •  2
  •   matyr    14 年前

    绑定到 keyup keydown / keypress

    滚动条保持插入符号在最下面一行

    scrollTop .

    <!DOCTYPE html>
    <title>autoindent example</title>
    <textarea id="TA" rows="8"></textarea>
    <script>
    document.getElementById('TA').addEventListener('keyup', function(v){
      if(v.keyCode != 13 || v.shiftKey || v.ctrlKey || v.altKey || v.metaKey)
        return;
      var val = this.value, pos = this.selectionStart;
      var line = val.slice(val.lastIndexOf('\n', pos - 2) + 1, pos - 1);
      var indent = /^\s*/.exec(line)[0];
      if(!indent) return;
      var st = this.scrollTop;
      this.value = val.slice(0, pos) + indent + val.slice(this.selectionEnd);
      this.selectionStart = this.selectionEnd = pos + indent.length;
      this.scrollTop = st;
    }, false);
    </script>
    <p>(not considering IE here)
    
        2
  •  1
  •   machineghost    14 年前

    你有没有注意到堆栈溢出文本区域是如何处理代码的?如果键入:

    function example(whatever) {
        Example Stuff // And then hit enter here
    }
    

    一开始,什么都不会发生。然后,当您缩进(通过键入或单击101010按钮)时,它会在代码上放置一个不同的背景。

    我认为类似的方法可能对你有用。与其尝试将所有内容都绑定到enter keypress事件,您应该做的是:

    1. 连接一个普通的onKeySomething事件,但不要只查找“enter”;每次按键后:

    2. 然后,actualFunction可以解析textarea的内容,按您喜欢的方式缩进内容,并且没有任何东西会中断用户的正常工作流程

    我知道这并不是真正的IDE的表现,但是考虑到JS和web的局限性,它可能是最好的方法。

        3
  •  0
  •   Matt L    14 年前

    如何子类化textbox并手动处理WndProc?这将使您获得更细粒度的控制,并将处理typematic键重复(KeyPress和类似事件仅在您按住键时触发一次)。

    public class MyTextBox : System.Windows.Forms.TextBox
    {
        protected override void WndProc(ref Message m)
        {
            // Let the O/S handle the key first
            base.WndProc(ref m);
    
            // Then, if it's the return key, append tabs
            int numTabs = 3;                 // TODO: insert your own value here
            const int WM_CHAR = 0x0102;
            if(m.Msg == WM_CHAR && (char)m.WParam == '\r')
            {
                m.WParam = new IntPtr('\t'); // Recycle m since base is done with it
                for (int i = 0; i < numTabs; i++)
                    WndProc(ref m);
            }
        }
    }
    
        4
  •  0
  •   NullUserException Mark Roddy    14 年前

    我知道这不是一个直截了当的答案,但在网上有一些例子,你可以看看,这将真正帮助你实现这一点。

    http://jsfiddle.net
    http://teddevito.com/demos/textarea.html
    http://thelackthereof.org/JQuery_Autoindent