首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“智能”文本区域自动缩进

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

Stack Overflow用户
提问于 2010-08-10 00:57:28
回答 4查看 2.5K关注 0票数 5

我正在尝试创建一个自动缩进文本区域,到目前为止,它可以使用以下代码。我遇到的问题是,我目前正在阻止按enter键的默认操作,以便计算行中的制表符,然后插入换行符。

这是可行的,但我希望textarea的默认操作,因为如果您按住enter向下,它将不会滚动文本区域,直到插入符号到达底部行,然后滚动条保持在底部行的插入符号。如果在文本区域的任何地方使用,下面的当前代码都会将插入符号保留在视野中,但是它会导致插入符号上方的内容向上滚动,这是一个妥协,因为插入符号不再消失。如果没有其他解决方案,这将很好,但我希望有其他的想法。

代码语言:javascript
复制
    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中,如果您键入以下内容

代码语言:javascript
复制
function example(whatever) {
     Example Stuff // And then hit enter here

我希望它能将您带到与“示例内容”相同的从左边框到选项卡的距离,以便使您的代码更易于阅读。我目前有这个功能,但问题是我正在拦截enter键,这意味着我必须提供这个功能。我很难复制不滚动文本框直到光标到达底部边框的确切功能。因此,如果要将enter保存在textarea的顶部,光标就会沿着textarea滚动,将任何文本移动到它的底部边框,然后textarea的滚动条将跟随光标。讲得通?

编辑2更新标记,以表明代码是用PHP编写的

我一直在做这件事,而这篇文章一直在做。我认为,当我有机会的时候,我要探讨的另一个选择是,不要阻止enter,而只是允许按enter的默认操作,并将字符串从lastIndexOf('\n')-1读取到最近的任何\t\n。我认为这会给我我正在寻找的字符串,但不会扰乱文本区域的行为。测试后将再次更新。

编辑3解决了,根据我上一次的更新,我决定在按下键后扫描字符串,保留自然行为(为感兴趣的人在下面添加的部分),唯一真正剩下的问题是,如果您持有enter,它将不会从enter按下的起始位置计数缩进,这对我来说很好。我要把这个给http://stackoverflow.com/users/15066/matyr'>matyr,虽然我在他回答之前就已经弄清楚了,他仍然是最接近的。

代码语言:javascript
复制
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);
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-08-14 04:41:50

我想要文本区域的默认操作

绑定到keyup而不是keydown/keypress并在本机中断后插入选项卡如何?

滚动条保持底部行插入符号。

您可以通过还原scrollTop来保留滚动位置。

代码语言:javascript
复制
<!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
EN

Stack Overflow用户

发布于 2010-08-14 02:41:32

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

代码语言:javascript
复制
function example(whatever) {
    Example Stuff // And then hit enter here
}

一开始,什么都不会发生。然后,当您进行缩进(输入或单击101010按钮)时,它会在代码中放置一个不同的背景。然后,在您等待一段时间之后,它的语法会对代码进行着色。但是,如果你再次开始打字,它会回到黑色/白色。

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

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

1A.设置一些全局变量(如。定时器)到新日期();

1B。actualFunction()

  • actualFunction (X,timeoutFunction),在用户停止输入

  • Create timeoutFunction之后,X需要等待很长时间;这个函数应该检查全局的" timer“变量,如果新的Date() -timer>X触发器timeoutFunction可以解析文本区域的内容,缩进任何您喜欢的内容,任何东西都不会中断用户

的正常事务流。

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

票数 1
EN

Stack Overflow用户

发布于 2010-08-14 03:28:53

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

代码语言:javascript
复制
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);
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3445276

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档