限制文本区域中的行数

Posted

技术标签:

【中文标题】限制文本区域中的行数【英文标题】:Limiting number of lines in textarea 【发布时间】:2010-10-08 02:12:00 【问题描述】:

我正在寻找一种可以限制用户在 textarea 中输入的行数的 javascript(行我的意思是用户在键盘上按 enter 结束的一些文本)。我找到了一些解决方案,但它们根本不起作用或表现得很奇怪。 最好的解决方案是可以完成这项工作的 jquery 插件 - 类似于 CharLimit,但它应该能够限制文本行数而不是字符数。

【问题讨论】:

定义“行”。可见线?用“\n”或其他东西分隔的行? 【参考方案1】:

这个可能帮助(可能最好使用 jQuery、onDomReady 并且不显眼地将 keydown 事件添加到 textarea)但在 IE7 和 FF3 中进行了测试:

<html>
  <head><title>Test</title></head>
  <body>
    <script type="text/javascript">
      var keynum, lines = 1;

      function limitLines(obj, e) 
        // IE
        if(window.event) 
          keynum = e.keyCode;
        // Netscape/Firefox/Opera
         else if(e.which) 
          keynum = e.which;
        

        if(keynum == 13) 
          if(lines == obj.rows) 
            return false;
          else
            lines++;
          
        
      
      </script>
    <textarea rows="4" onkeydown="return limitLines(this, event)"></textarea>
  </body>
</html>

*Edit - 解释:如果按下 ENTER 键,它会捕获按键,如果 textarea 中的行与 textarea 的行数相同,则不会添加新行。否则它会增加行数。

编辑#2:考虑到人们仍在接受这个答案,我想我会尽可能地更新它以处理粘贴、删除和剪切。

<html>

<head>
    <title>Test</title>
    <style>
        .limit-me 
            height: 500px;
            width: 500px;
        
    </style>
</head>

<body>
<textarea rows="4" class="limit-me"></textarea>

<script>
    var lines = 1;

    function getKeyNum(e) 
        var keynum;
        // IE
        if (window.event) 
            keynum = e.keyCode;
            // Netscape/Firefox/Opera
         else if (e.which) 
            keynum = e.which;
        

        return keynum;
    

    var limitLines = function (e) 
        var keynum = getKeyNum(e);

        if (keynum === 13) 
            if (lines >= this.rows) 
                e.stopPropagation();
                e.preventDefault();
             else 
                lines++;
            
        
    ;

    var setNumberOfLines = function (e) 
        lines = getNumberOfLines(this.value);
    ;

    var limitPaste = function (e) 
        var clipboardData, pastedData;

        // Stop data actually being pasted into div
        e.stopPropagation();
        e.preventDefault();

        // Get pasted data via clipboard API
        clipboardData = e.clipboardData || window.clipboardData;
        pastedData = clipboardData.getData('Text');

        var pastedLines = getNumberOfLines(pastedData);

        // Do whatever with pasteddata
        if (pastedLines <= this.rows) 
            lines = pastedLines;
            this.value = pastedData;
        
        else if (pastedLines > this.rows) 
            // alert("Too many lines pasted ");
            this.value = pastedData
                .split(/\r\n|\r|\n/)
                .slice(0, this.rows)
                .join("\n ");
        
    ;

    function getNumberOfLines(str) 
        if (str) 
            return str.split(/\r\n|\r|\n/).length;
        

        return 1;
    

    var limitedElements = document.getElementsByClassName('limit-me');

    Array.from(limitedElements).forEach(function (element) 
        element.addEventListener('keydown', limitLines);
        element.addEventListener('keyup', setNumberOfLines);
        element.addEventListener('cut', setNumberOfLines);
        element.addEventListener('paste', limitPaste);
    );
</script>
</body>
</html>

【讨论】:

当用户点击退格键导致整行删除时会出现问题,这将限制可写入的行数,并可能删除所有行,只留下一行写。当用户输入大量字符使他们移入新行但随后创建的行不计入限制行时,它也表现不佳。 我创建了一个带有 jquery 和 bootstrap 的助手来在 textarea 上应用规则,并且当用户在其中粘贴代码时它也会验证。这是我的第一个 gitHub 项目。免费使用和修改。 github.com/werddomain/TextAreaLimitation【参考方案2】:

如何使用 jQuery:

绑定到 textarea 的 keyDown 事件。

function limitTextareaLine(e) 
    if(e.keyCode == 13 && $(this).val().split("\n").length >= $(this).attr('rows'))  
        return false;
    

【讨论】:

您好 Maciej,感谢您的回答。你能举个例子吗? 当用户将换行符粘贴到文本区域时,此策略失败。【参考方案3】:

jQuery 示例。这适用于打字和粘贴。

  //Limit to # of rows in textarea or arbitrary # of rows
  $('#yourtextarea').bind('change keyup', function(event) 
    //Option 1: Limit to # of rows in textarea
    rows = $(this).attr('rows');
    //Optiion 2: Limit to arbitrary # of rows
    rows = 6;

    var value = '';
    var splitval = $(this).val().split("\n");

    for(var a=0;a<rows && typeof splitval[a] != 'undefined';a++) 
      if(a>0) value += "\n";
      value += splitval[a];
    
    $(this).val(value);
  );

【讨论】:

【参考方案4】:

此解决方案有效:

<script type="text/javascript">
    function limitTextarea(textarea, maxLines, maxChar) 
        var lines = textarea.value.replace(/\r/g, '').split('\n'), lines_removed, char_removed, i;
        if (maxLines && lines.length > maxLines) 
            lines = lines.slice(0, maxLines);
            lines_removed = 1
        
        if (maxChar) 
            i = lines.length;
            while (i-- > 0) if (lines[i].length > maxChar) 
                lines[i] = lines[i].slice(0, maxChar);
                char_removed = 1
            
            if (char_removed || lines_removed) 
                textarea.value = lines.join('\n')
            
        
    
</script>

文本区域是

<asp:TextBox ID="myWishTB" runat="server" Height="185px" TextMode="MultiLine" 
             Style="overflow: auto;" Width="95%" 
             onkeyup="limitTextarea(this,10,80)">
</asp:TextBox>

在常规 HTML 中:

<textarea id="textareaID" onkeyup="limitTextarea(this,5,100)" cols="20" rows="5">   </textarea>

【讨论】:

【参考方案5】:

(用 jquery 完成)。它并不完美,但关心包装。不仅仅取决于行尾 (\n)。 如果 textarea 中的 css overflow 属性不是 auto,则 jquery 滚动事件在 mozilla 和 firefox 中存在问题,否则删除相应的行并设置溢出隐藏。可以帮助 css 调整大小:无和固定高度。

$('#textarea').scroll(function () 
    $(this).css("overflow", "hidden");      /* for the mozilla browser problem */
    $(this).animate(scrollTop: $(this).outerHeight());
    while ($(this).scrollTop() > 0)        /* for the copy and paste case */               
        lines=$(this).val().slice(0,-1);
        $(this).val(lines);
    
    $(this).css("overflow", "auto");        /* For the mozilla browser problem */
);

【讨论】:

【参考方案6】:

给定文本块的可见/显示行数会因不同的浏览器、使用的字体等而异。您必须至少设置一个特定的字体和字体大小,才能半- 可靠地计算显示行数。

更新:我看到了编辑。然后像 kevchadders 代码这样的东西应该适合你。您将需要 js 来计算字符和 '\r\n' 并检查用户定义的限制。此外,如果您不使用他的脚本,请确保使用涉及时间间隔检查和/或 textarea 的 onKeyDown/onKeyUp 事件的脚本。这可能就是您测试过的某些脚本看起来“行为异常”的原因。

【讨论】:

【参考方案7】:

这与伊万的回答基本相同,使用 jQuery。我为自己的项目对其进行了测试;似乎工作正常。

<script type="text/javascript" charset="utf-8">
  $(function() 
  
    function getLines(id)
    
      return $('#' + id).val().split("\n").length
    

  $('#testing').keyup(function() 
  
    var allowedNumberOfLines = 4;

    if(getLines('testing') > allowedNumberOfLines)
    
      modifiedText = $(this).val().split("\n").slice(0, allowedNumberOfLines);
      $(this).val(modifiedText.join("\n"));
    
  );
);
</script>

【讨论】:

getLines(id) 应该是 getLines(el) 其中 $('#testing') 直接发送到 getLines 函数。一个简单的优化。 但这是否适用于您键入时自动换行的单词?您的函数仅依赖于换行符。【参考方案8】:

我对其进行了一些扩展,以检测甚至溢出而无需手动换行。这适用于具有“溢出:隐藏”的固定大小的文本区域。

目前,如果字体不适合 textarea,我的解决方案会使字体变小。如果可能的话,让它变大。

var keynum, allowedLines = 5, defaultFontSize = 13/*px*/;

$(document).ready(function() 
    $("textarea").keydown(function(e, obj) 
        if(window.event)
            keynum = e.keyCode;
        else if (e.which)
            keynum = e.which;

        if (keynum == 13 && allowedLines <= $(this).val().split("\n").length)
            return false;
    );
    $("textarea").keyup(function(e, obj) 
        // Avoid copy-paste
        if (allowedLines < $(this).val().split("\n").length)               
            lines = $(this).val().split("\n").slice(0, allowedLines);
            $(this).val( lines.join('\n') );
        

        // Check overflow
        if ((this.clientHeight < this.scrollHeight)) 
            while ((this.clientHeight < this.scrollHeight)) 
                currFontSize = $(this).css('font-size');
                finalNum = parseFloat(currFontSize, 11);
                stringEnding = currFontSize.slice(-2);
                $(this).css('font-size', (finalNum-1) + stringEnding);
            
         else if ($(this).css('fontSize') != defaultFontSize+'px')  
            while ($(this).css('font-size') != defaultFontSize+'px') 
                // First lets increase the font size
                currFontSize = $(this).css('font-size');
                finalNum = parseFloat(currFontSize, 11);
                stringEnding = currFontSize.slice(-2);
                $(this).css('font-size', (finalNum+1) + stringEnding);
                // lets loop until its enough or it gets overflow again
                if(this.clientHeight < this.scrollHeight) 
                    // there was an overflow and we have to recover the value
                    $(this).css('font-size', currFontSize);
                    break;
                
            
        
    );
);

【讨论】:

以上是关于限制文本区域中的行数的主要内容,如果未能解决你的问题,请参考以下文章

Jquery限制文本区域中的文本

严格限制 textarea Angular 中的行数

限制文本区域中的字数

Android 应用 (Cordova) 上的文本区域中的字数超出限制

文本区域字符限制

给定一个文本区域,有没有办法根据行数限制长度?