Chrome 在 textarea 中使用 maxlength 属性计数错误的字符

Posted

技术标签:

【中文标题】Chrome 在 textarea 中使用 maxlength 属性计数错误的字符【英文标题】:Chrome counts characters wrong in textarea with maxlength attribute 【发布时间】: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:

【问题讨论】:

类似:***.com/q/12924591/266535 或者或者可能是这样的:***.com/questions/11839413/… 【参考方案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 个字符。

【讨论】:

尖尖 -- I just asked a question related to this OP 对-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

【讨论】:

以上是关于Chrome 在 textarea 中使用 maxlength 属性计数错误的字符的主要内容,如果未能解决你的问题,请参考以下文章

在 Chrome 和 Firefox 中使用换行符对 textarea 进行不同的 maxlength 验证

JavaScript 更新 textarea 冻结 Chrome,但不冻结 Firefox

如何限制 chrome 中的最大 textarea 宽度和高度或如何禁用 textarea 调整大小

css3“新”样式的flexbox无法在chrome中拉伸textarea

取消chrome浏览器下input和textarea的默认样式

<foreignObject> 中的 <textarea> 在 Chrome 中按预期处理,但在 Firefox 中没有