【问题标题】:Chrome counts characters wrong in textarea with maxlength attributeChrome 在 textarea 中使用 maxlength 属性计数错误的字符
【发布时间】:2012-04-19 07:55:05
【问题描述】:

这是一个例子:

$(function() {
  $('#test').change(function() {
    $('#length').html($('#test').val().length)
  })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id=test maxlength=10></textarea>
length = <span id=length>0</span>

用行(一行一个字符)填充文本区域,直到浏览器允许。 完成后离开textarea,js代码也会计算字符。

所以在我的情况下,在 chrome 阻止我之前,我只能输入 7 个字符(包括空格)。虽然 maxlength 属性的值为 10:

【问题讨论】:

标签: javascript html google-chrome textarea maxlength


【解决方案1】:

以下是如何让您的 javascript 代码匹配浏览器认为文本区域中的字符数量:

http://jsfiddle.net/FjXgA/53/

$(function () {
    $('#test').keyup(function () {
        var x = $('#test').val();

        var newLines = x.match(/(\r\n|\n|\r)/g);
        var addition = 0;
        if (newLines != null) {
            addition = newLines.length;
        }

        $('#length').html(x.length + addition);
    })
})

基本上,您只需计算文本框中的总换行符,然后将每个换行符的字符数加 1。

【讨论】:

  • 也可以写成:$('#length').html(x.replace(/(\r\n|\n|\r)/g, '--').length);
  • 这在 Firefox 中会出错,因为它将换行符计为 1 个字符
  • @Stalinko 我刚刚在 Firefox、Chrome、IE、Edge 和 Opera 中进行了测试。它似乎在所有这些中都起作用。换行符将长度加 2。这是你看到的还是你的意思是别的?
  • @Tim,即使脚本正确显示长度,如果已经存在回车,它也允许输入更多字符。输入 2 个回车后,我可以输入 12 个字符。
【解决方案2】:

当涉及到 maxlength 时,您的回车每个被视为 2 个字符。

1\r\n
1\r\n
1\r\n
1

但似乎 javascript 只能是 \r\n 之一(我不确定是哪一个),它只能加起来 7

【讨论】:

  • 我已经在 Chrome 和 Firefox 中记录了关于这个问题的错误;它似乎已在 Chrome 的最新版本中修复。
  • @Pointy 我在 Chrome 的开发版 (19.0.1084.1) 中,但我仍然有这个问题。
  • 是的,我也这么认为。但是为什么js不把回车算作2个字符呢?有没有办法让它做到这一点?
  • 当文本区域的内容实际发布时,嵌入的换行必须作为 CR LF 对传输。因此,正确的做法是让浏览器报告内容的长度,就像换行符花费 2 个字符一样。
  • @Neal 哦,好吧,我正在对 OP 发表评论。这似乎是一个非常严重的问题,因为它使“maxlength”属性基本上无用。
【解决方案3】:

根据上面 Pointy 的回答,似乎正确的方法是将所有新行计为两个字符。这将使其跨浏览器标准化,并与发布时发送的内容相匹配。

所以我们可以按照规范,用回车 - 换行对替换所有出现的回车不跟新行,以及所有新行不跟回车。

var len = $('#test').val().replace(/\r(?!\n)|\n(?!\r)/g, "\r\n").length;

然后使用那个变量来显示textarea值的长度,或者限制它,等等。

【讨论】:

    【解决方案4】:

    由于未知的原因,jQuery 总是将 &lt;textarea&gt; 值中的所有换行符转换为单个字符。也就是说,如果浏览器给它\r\n 换行,jQuery 会确保它在.val() 的返回值中只是\n

    Chrome 和 Firefox 都以相同的方式计算 &lt;textarea&gt; 标签的长度,以达到“最大长度”的目的。

    但是,HTTP 规范坚持将换行符表示为 \r\n。因此,jQuery、webkit 和 Firefox 都犯了这个错误。

    如果你的服务器端代码确实有一个固定的最大字段值大小,那么&lt;textarea&gt; 标签上的“maxlength”几乎没有用。

    edit — 在这一点上(2014 年末),Chrome (38) 的行为似乎正常。但是,Firefox (33) 仍然不将每个硬返回计为 2 个字符。

    【讨论】:

    • 对-o - 我会复制到那里。
    • 您似乎在说 .val() 返回错误(1 个字符),但浏览器正确地将其视为 2 个字符,因此 maxlength 将考虑每个换行符的 2 个字符。如果是这种情况,并且您的后端数据库有一个固定的最大值,我看不出maxlength 有什么用处,因为它正确计算了将保存在数据库中的字符数。
    • @wired_in hi 再次 :) 问题是内置的 maxlength 检查确实 not 考虑到 CR 字符。这意味着内置的 maxlength 将允许 textarea 在客户端中包含比允许的更多的 actual 字符。因此,如果您有一个长度为 500 个字符的数据库字段,并且您说 maxlength=500,则发布的表单可能包含 超过 500 个字符的值。因此该属性是无用的。
    • @Pointy 这与这个问题相矛盾。 OP 说他有一个 textarea,maxlength 为 10,但是当他在 textarea 中输入时,他只能输入 7 个字符(每个换行符包括 1 个字符)。这清楚地表明 maxlength 正在考虑每个新行的 2 个字符。我自己的测试证实了这一点......
    【解决方案5】:

    看起来 javascript 也在考虑换行符的长度。

    尝试使用:

    
    var x = $('#test').val();
    
    x = x.replace(/(\r\n|\n|\r)/g,"");    
    
    $('#length').html(x.length);
    
    

    我在你的小提琴中使用它并且它正在工作。希望这会有所帮助。

    【讨论】:

      【解决方案6】:

      这是因为一个新行实际上是 2 个字节,因此是 2 个长。 JavaScript 不这样看,因此它只会计数 1,总共 7(3 个新行)

      【讨论】:

        【解决方案7】:

        这是一个更通用的解决方案,它覆盖了 jQuery 'val' 函数。很快将把这个问题写成一篇博文并在此处链接。

        var originalVal = $.fn.val;
        $.fn.val = function (value) {
            if (typeof value == 'undefined') {
                // Getter
        
                if ($(this).is("textarea")) {
                    return originalVal.call(this)
                        .replace(/\r\n/g, '\n')     // reduce all \r\n to \n
                        .replace(/\r/g, '\n')       // reduce all \r to \n (we shouldn't really need this line. this is for paranoia!)
                        .replace(/\n/g, '\r\n');    // expand all \n to \r\n
        
                    // this two-step approach allows us to not accidentally catch a perfect \r\n
                    //   and turn it into a \r\r\n, which wouldn't help anything.
                }
        
                return originalVal.call(this);
            }
            else {
                // Setter
                return originalVal.call(this, value);
            }
        };
        

        【讨论】:

        • btw 很棒的博文
        【解决方案8】:

        如果要获取文本区域的剩余内容长度,则可以在包含换行符的字符串上使用 match。

        HTML:

        <textarea id="content" rows="5" cols="15" maxlength="250"></textarea>
        

        JS:

        var getContentWidthWithNextLine = function(){
            return 250 - content.length + (content.match(/\n/g)||[]).length;
        }
        

        【讨论】:

          【解决方案9】:
          var value = $('#textarea').val();
          var numberOfLineBreaks = (value.match(/\n/g)||[]).length;
          $('#textarea').attr("maxlength",500+numberOfLineBreaks);
          

          已经在 IE 中的 google 上完美运行必须避免脚本!在 IE 中,'break-line' 只计算一次,因此请避免在 IE 中使用此解决方案!

          【讨论】:

          • 粘贴失败。
          【解决方案10】:

          文本区域在浏览器之间仍未完全同步。我注意到两个主要问题:回车和字符编码

          回车

          默认为 2 个字符 \r\n(Windows 风格)。

          问题在于 Chrome 和 Firefox 会将其视为一个字符。您也可以选择它来观察有一个隐形字符被选中作为空格。

          在此处找到解决方法:

          var length = $.trim($(this).val()).split(" ").join("").split('\n').join('').length;
          

          Jquery word counts when user type line break

          另一方面,Internet Explorer 会将其计为 2 个字符。

          他们的代表是:

          二进制: 00001101 00001010

          十六进制: 0D0A

          ,在 UTF-8 中表示为 2 个字符,maxlength 计为 2 个字符。

          HTML 实体可以是

          1) 由 javascript 代码创建:

          <textarea id='txa'></textarea>
          
          document.getElementById("txa").value = String.fromCharCode(13, 10);
          

          2) 从textarea的内容解析:

          Ansi 代码:

          <textarea>Line one.&#13;&#10;Line two.</textarea>
          

          3) 从键盘 Enter 键插入

          4) 定义为文本框的多行内容

          <textarea>Line one.
          Line two.</textarea>
          

          字符编码

          像 textarea 这样的输入字段的字符编码独立于页面的字符编码。如果您打算计算字节数,这很重要。因此,如果您有一个元标头来定义页面的 ANSI 编码(每个字符 1 个字节),则文本框的内容仍然是 UTF-8,每个字符 2 个字节。

          这里提供了字符编码的解决方法:

          function htmlEncode(value){
            // Create a in-memory div, set its inner text (which jQuery automatically encodes)
            // Then grab the encoded contents back out. The div never exists on the page.
            return $('<div/>').text(value).html();
          }
          
          function htmlDecode(value){
            return $('<div/>').html(value).text();
          }
          

          HTML-encoding lost when attribute read from input field

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-07
            • 2014-06-17
            • 2014-08-28
            • 2021-03-28
            相关资源
            最近更新 更多